####

Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 (CC BY-NC 3.0) United States License.

To cite this case study please use:

Wright, Carrie, and Ontiveros, Michael and Jager, Leah and Taub, Margaret and Hicks, Stephanie. (2020). https://opencasestudies.github.io/ocs-bp-opioid-rural-urban/ocs_pop.html. Opioids in the United States (Version v1.0.0).

avocado update url ####

Motivation


In this case study we will be examining the number of opioid pills (specifically oxycodone and hydrocodone, as they are the top two abused opioids) shipped to pharmacies and paractitionaers at the county-level around the United States (US) from 2006 to 2014.

This data comes from the DEA Automated Reports and Consolidated Ordering System (ARCOS) and was released by the Washington Post after legal action by the owner of the Charleston Gazette-Mail in West Virginia and the Washington Post.

We will investigate how the number of shipped pills compares for rural and urban counties. This analysis will demonstrate how different regions of the country may have been more at risk for opioid addiction crises due to differing rates of opioid prescription (using the number of pills as a proxy for perscription rates). This will help inform students about how evidence-based intervention decisions are made in this area.

This case study is motivated by this article:

García, M. C. et al. Opioid Prescribing Rates in Nonmetropolitan and Metropolitan Counties Among Primary Care Providers Using an Electronic Health Record System — United States, 2014–2017. MMWR Morb. Mortal. Wkly. Rep. 68, 25–30 (2019). DOI: 10.15585/mmwr.mm6802a1

This article explores rates of opioid perscriptions in rural and urban communties in the United States using the Athenahealth electronic health record (EHR) system for 31,422 primary care providers from January 2014 to March 2017.

The main takeaways from this article were:

Among 70,237 fatal drug overdoses in 2017, prescription opioids were involved in 17,029 (24.2%).

The percentage of patients prescribed an opioid was higher in rural than in urban areas.

Higher opioid prescribing rates put patients at risk for addiction and overdose.

Indeed, this was confirmed by another article which surveyed heroin users.

Cicero, T. J., Ellis, M. S., Surratt, H. L. & Kurtz, S. P. The Changing Face of Heroin Use in the United States: A Retrospective Analysis of the Past 50 Years. JAMA Psychiatry 71, 821 (2014). DOI:10.1001/jamapsychiatry.2014.366

They found that:

Respondents who began using heroin in the 1960s were predominantly young men (82.8%; mean age, 16.5 years) whose first opioid of abuse was heroin (80%).

However, more recent users were older (mean age, 22.9 years) men and women living in less urban areas (75.2%) who were introduced to opioids through prescription drugs (75.0%).

Heroin use has changed from an inner-city, minority-centered problem to one that has a more widespread geographical distribution, involving primarily white men and women in their late 20s living outside of large urban areas.

Photo by James Yarema on Unsplash

Main Questions


Our main question:

How did opioid shipment rates differ between rural and urban regions over time around the US from 2006-2014?

Learning Objectives


In this case study, we will demonstrate how to obtain data from an Application Programming Interface (API), which is an interface that allows users to more easily interact with a database. We will also especially focus on using packages and functions from the Tidyverse, such as dplyr, tidyr. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R more legible and intuitive.

The skills, methods, and concepts that students will be familiar with by the end of this case study are:

Data science skills:

  1. Importing data from an API (httr and jasonlite)
  2. How to reshape data by pivoting between “long” and “wide” formats and drop rows with NA values (tidyr)
  3. How to join data with dplyr
  4. How to create formatted tables of data with formattable
  5. How to create data visualizations with ggplot2
  6. How to look for missing data in a dataset (naniar)

Statistical concepts and methods:

  1. Understanding of when and why data normalization is useful
  2. Understanding of when and why data transformation is useful
  3. How to implement a t-test in R
  4. How to interpte a t-test in R

We will begin by loading the packages that we will need:

Packages used in this case study:

Package Use in this case study
here to easily load and save data
readr to import the data as a csv file
tibble to create tibbles (the tidyverse version of dataframes)
dplyr to filter, subset, join, add rows to, and modify the data
stringr to manipulate character strings within the data (collapsing strings together, replace values, and detect values)
magrittr to pipe sequential commands
tidyr to change the shape or format of tibbles to wide and long, to drop rows with NA values, and to see the last few columns of a tibble
ggmap to geocode the data (which means get the latitude and longitude values)
sf to modify the geocoded data so that overlapping points did not overlap
lubridate to work with the data-time data
DT to create the interactive table
htmltools to add a caption to our interactive table
ggplot2 to create plots
ggforce to create a plot zoom
forcats to reorder factor for plot
waffle to make waffle proportion plots
poliscidata to get population values for the states
flexdashboard to create the dashboard
shiny to allow our dashboard to be interactive
leaflet to implement the leaflet (a JavaScript library for maps) to create the map for our dashboard

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

Context


What exactly are opioids?

According to the DEA and the Alta Mira addiction treatment center:

Opioids (also known as narcotics which comes from the Greek word for “stupor”), describes a class of drugs that contain opium (the poppy plant - Papaver somniferum), are derived from opium, or contain a semi-synthetic or synthetic substitute for opium.

Photo by Ingo Doerrie on Unsplash

Hoewver, technically, opioids are substances that bind to the opioid receptors in the body, which are involved in the sensation of pain and the experience of reward. There are actually opioids that naturally are made by the human body, the most well known being the endorphins.

Oppoid drugs tend to be addictive becuase they modulate the reward system. This is the part of the brain that reinforces behaviors (normally these are behaviours such as drinking water or eating food) by causing the experience of pleasure (through the release of a neurotransmitter called dopamine).

This same system can be activated by both opioids that naturally occur in the body, as well as opioid perscription drugs and other addictive drugs. Activation of this sytem by drug use leads to very high releases of Dopamine and the sensation of pleasure which ultimately leads to reinforced use of that drug.

[source]

In general, opioids medications and drugs have been found to dull the senses, releive pain, supress cough, reduce respiration and heart rate, induce constipation, and induce feelings of euphoria. They have a high potential for abuse and addiction.

Drugs within this class include (with perscription drug brand names are shown in parentheses):

  1. Non-synthetic purified: Morhpine, Codeine, Thebaine
  2. Semi-synthetic: Heroin, Oxycodone (OxyContin, Oxecta, Roxicodone), and Hydrocodone ( Vicodin, Lortab, Lorcet)), oxymorphone (Opana), Hydromorphone (Dilaudid, Exalgo)
  3. Synthetic: Meperidine (Demerol), Methadone (Methadose, Dolophine), and Fentanyl (Abstral, Actiq, Fentora, Duragesic, Lazanda, Subsys), Tramadol (ConZip, Ryzolt, Ultram)

[source]

Opium comes from the fluid (which is also called poppy tears) inside the seed capusules of the Papaver somniferum plant. This contains morphine, codeine, and thebaine. This is then dried.

Opium has been used by humans since 5000 BCE and it has been used across the world. See here for an interesting overview of the history.

Opium derived medications were historically used in United States to treat a variety of ailments besides pain including: cholera, dysentery, tubuerculosi, and mental illness.

Of note, they state that “from 1898 to 1910 heroin was marketed as a non-addictive morphine substitute and cough medicine for children”!

Here you can see a photo of a bottle of herion:

[source]

Opioids have continued to be used in the treatment of pain.

The Opioid Epidemic

The opioid epidemic began in the late 1990s.

According to the US department of health and human services (HHS):

In the late 1990s, pharmaceutical companies reassured the medical community that patients would not become addicted to opioid pain relievers and healthcare providers began to prescribe them at greater rates.

Increased prescription of opioid medications led to widespread misuse of both prescription and non-prescription opioids before it became clear that these medications could indeed be highly addictive.

In 2017 the HHS declared a public health emergency

See here for a timeline of the epidemic in the US and here for more detials about the epidemic.

According to this article from the Morbidity and Mortality Weekly Report (MMWR) of the Centers for Disease Control and Prevention (CDC):

Drug overdose is the leading cause of unintentional injury-associated death in the United States.

[source]

According to the CDC, there were 3 waves of the epidemic:

[source]

You can see that moth recent overdose deaths were due to the use of synthetic opioids, where as previous high levels of overdoses (till about 2015) were attributable to natural and semi-synthetic opioids (which is what we will look at in this case study).

They state that:

From 1999–2018, almost 450,000 people died from an overdose involving any opioid, including prescription and illicit opioids.

Importantly rates appear to differ across states, according to this CDC report

[source]

According to the motivating report for our case study:

Perscription rates are now declining, however, perscription of opioids was found to be higher in rural areas rather than urban ares.

[source]

It is important to identify locations where people are particularly vulernable to target interventions for communities that need it the most.

Limitations


There are some important considerations regarding this data analysis to keep in mind:

According to the [Washington Post data](https://www.washingtonpost.com/national/2019/07/18/how-download-use-dea-pain-pills-database/ about the DEA data:

“It’s important to remember that the number of pills in each county does not necessarily mean those pills went to people who live in that county. The data only shows us what pharmacies the pills are shipped to and nothing else.”

Furthermore, we will define counties as being rural or urban however there can be great variation within a county and we used land area values form only 2010 even though these can fluctuate. Therefore the way we categorized counties should be seen as an approximation.

Finally, overdose deaths are often due to the use of multiple substances. Simply because a county recieved more pills does not mean that people in that county would experience more drug overdoses. It is also important to remember that perscription opioids only account for a portion of the drug overdose deaths reported in this time period. However, according to this article 75% of heroin users surveyed were introduced to opioids through perscription drug use.

What are the data?


We will use data from two sources:

  1. The US census for land area of counties to allow us to extimate county-level population density

  2. The Washington Post datafrom the Drug Enforcement Administration (DEA) about opioid (oxycodone and hydrocodone) pill shipments to pharmacies and paractitionaers around the US at the county-level

This dataset was released in July of 2019 and has been controversial as according to the Washington Post:

The disclosure is part of a civil action brought by 2,500 cities, towns, counties and tribal nations alleging that nearly two dozen drug companies conspired to saturate the nation with opioids.

See here for more details about how this database was released.

The Washington Poststates that they:

.. cleaned the data to include only information on shipments of oxycodone and hydrocodone pills. We did not include data on 10 other opioids because they were shipped in much lower quantities…

It’s important to remember that the number of pills in each county does not necessarily mean those pills went to people who live in that county. The data only shows us what pharmacies the pills are shipped to and nothing else.

This data was part of the [Automated Reports and Consolidated Ordering System (ARCOS)]https://www.deadiversion.usdoj.gov/arcos/retail_drug_summary/ of the DEA in which:

manufacturers and distributors report their controlled substances transactions

Their website indicates that:

The Controlled Substances Act of 1970 created the requirement for Manufacturers and Distributors to report their controlled substances transactions to the Attorney General. The Attorney General delegates this authority to the Drug Enforcement Administration (DEA).

ARCOS is an automated, comprehensive drug reporting system which monitors the flow of DEA controlled substances from their point of manufacture through commercial distribution channels to point of sale or distribution at the dispensing/retail level - hospitals, retail pharmacies, practitioners, mid-level practitioners, and teaching institutions. Included in the list of controlled substance transactions tracked by ARCOS are the following: All Schedules I and II materials (manufacturers and distributors); Schedule III narcotic and gamma-hydroxybutyric acid (GHB) materials (manufacturers and distributors); and selected Schedule III and IV psychotropic drugs (manufacturers only).

The annual report about the data from 2019, can be found here.

As this is a very large dataset, thus the Washington Post created an application prgoramming interface (API) to make it easier for users to access the data.

An API is a computational interface that simplifies interactacts with a data or file system for a user. It is similar to a Graphical User Interface GUI, yet it allows the user some more flexibility/functionality.

This link takes you to the Washington Post ARCOS API.

There was also an R package on cran called arcos for interacting with the API, but this has been archived. This package is however still available here on Github.

See here for more information about how to get access the Washington Post DEA database.

Data Import


Land Area

We will need land area data for our calculations of population density.

We obtained county land area data from the US census Bureau at this link

This link explains how the data is formated.

We will use the read_excel() function of the readxl package to import the data. We will also convert the data into a tibble (which is a the tidyverse version of a data frame) by using the as_tibble() function of the tibble package.

We can take a look at the data using the base head() function which will show the frist 6 rows.

# A tibble: 6 x 34
  Areaname STCOU LND010190F LND010190D LND010190N1 LND010190N2 LND010200F
  <chr>    <chr>      <dbl>      <dbl> <chr>       <chr>            <dbl>
1 UNITED … 00000          0   3787425. 0000        0000                 0
2 ALABAMA  01000          0     52423. 0000        0000                 0
3 Autauga… 01001          0       604. 0000        0000                 0
4 Baldwin… 01003          0      2027. 0000        0000                 0
5 Barbour… 01005          0       905. 0000        0000                 0
6 Bibb, AL 01007          0       626. 0000        0000                 0
# … with 27 more variables: LND010200D <dbl>, LND010200N1 <chr>,
#   LND010200N2 <chr>, LND110180F <dbl>, LND110180D <dbl>, LND110180N1 <chr>,
#   LND110180N2 <chr>, LND110190F <dbl>, LND110190D <dbl>, LND110190N1 <chr>,
#   LND110190N2 <chr>, LND110200F <dbl>, LND110200D <dbl>, LND110200N1 <chr>,
#   LND110200N2 <chr>, LND110210F <dbl>, LND110210D <dbl>, LND110210N1 <chr>,
#   LND110210N2 <chr>, LND210190F <dbl>, LND210190D <dbl>, LND210190N1 <chr>,
#   LND210190N2 <chr>, LND210200F <dbl>, LND210200D <dbl>, LND210200N1 <chr>,
#   LND210200N2 <chr>

Looks good!

Accessing APIs

The httr package formats what are called “GET requests” so that they will work properly. This allows for the data to be retrieved from the API.

The jsonlite package alows you to convert the data from JSON (often used by APIs) to a differet format that is easier to work with.

APIs typically require a password or key to gain access. Thus the httr package helps to authenticate your data request. Often these keys are something that you do not want to share, unless the API is public.

In our case the API is indeed public, and currently “uO4EK6I” is publicly published as a key to use on the github page for the arcos package. We will use that here to access the API.

Population Data

We are interested in the county level data - first let’s get the population data. We can access it by:

  1. Pressing the GET button on the API.

  1. Pressing the “Try it out” button.

  1. Entering the key (which we got from here).

  1. Clicking the “Execute” button.

This gives us the following output:

curl -X GET "https://arcos-api.ext.nile.works/v1/county_population?key=uO4EK6I" -H "accept: application/json"

We can copy the URL section "https://arcos-api.ext.nile.works/v1/county_population?key=uO4EK6I" and use it in the GET() function of the httr package :

If we needed to specify a username and password, we would do so using the authenticate() function of the httr package within the GET function. The authenticate() function takes user, password and type arguments.

Here is an example:

The default type is "basic" and typcally what is needed.

Now that we have used the GET function, we have a JavaScript Object Notation (JSON) file of the data.

JSON files are lightweight meaning that they don’t take up much memory and they are human readible files to make transmitting data from websites easier.

Response [https://arcos-api.ext.nile.works/v1/county_population?key=uO4EK6I]
  Date: 2020-09-18 20:19
  Status: 200
  Content-Type: application/json
  Size: 5.75 MB

Here we can see that the object called countyjson is a json object. You will also see that the Satus is 200, which means that we were sucessful in retreiving the data from the API.

Now we can use the content() funtion of the httr package to extract the text from the file:

This will be a very large string at this point, we can take a look at part of it by using the str_sub() function of the stringr package. In this case we will only look at the first 400 characters.

What is a string or a chracter?


Click here for an explanation about character strings if you are not yet familiar

There are several classes of data in R programming. Character is one of these classes. A character string is an individual data value made up of characters. This can be a paragraph, like the legend for the table, or it can be a single letter or number like the letter "a" or the number "3".

If data are of class character, than the numeric values will not be processed like a numeric value in a mathematical sense.


[1] "[{\"BUYER_COUNTY\":\"AUTAUGA\",\"BUYER_STATE\":\"AL\",\"countyfips\":\"01001\",\"STATE\":1,\"COUNTY\":1,\"county_name\":\"Autauga\",\"NAME\":\"Autauga County, Alabama\",\"variable\":\"B01003_001\",\"year\":2006,\"population\":51328},{\"BUYER_COUNTY\":\"BALDWIN\",\"BUYER_STATE\":\"AL\",\"countyfips\":\"01003\",\"STATE\":1,\"COUNTY\":3,\"county_name\":\"Baldwin\",\"NAME\":\"Baldwin County, Alabama\",\"variable\":\"B01003_001\",\"year\":2006,\"population\":168121"

Now to get the data into a more readible format , we can use the fromJSON() function of the jsonlite package and again create a tibble of the data using as_tibble()

We can use the glimpse() function and the distinct() function of the dplyr package to get a better sense of the data. The distinct() function allows us to take a look at the unique values of the year variable.

Rows: 28,265
Columns: 10
$ BUYER_COUNTY <chr> "AUTAUGA", "BALDWIN", "BARBOUR", "BIBB", "BLOUNT", "BULL…
$ BUYER_STATE  <chr> "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "A…
$ countyfips   <chr> "01001", "01003", "01005", "01007", "01009", "01011", "0…
$ STATE        <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ COUNTY       <int> 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 3…
$ county_name  <chr> "Autauga", "Baldwin", "Barbour", "Bibb", "Blount", "Bull…
$ NAME         <chr> "Autauga County, Alabama", "Baldwin County, Alabama", "B…
$ variable     <chr> "B01003_001", "B01003_001", "B01003_001", "B01003_001", …
$ year         <int> 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 20…
$ population   <int> 51328, 168121, 27861, 22099, 55485, 10776, 20815, 115388…
# A tibble: 9 x 1
   year
  <int>
1  2006
2  2007
3  2008
4  2009
5  2010
6  2011
7  2012
8  2013
9  2014

It looks like we have the full data from 2006-2014.

We are also interested in opioid pill shipment data at the county level.

Annual Shipment Data

Here is the result of the same steps using the API for the combined_county_annual data:

curl -X GET "https://arcos-api.ext.nile.works/v1/combined_county_annual?key=uO4EK6I" -H "accept: application/json"

Question Opportunity

See if you can fix import the data without looking at the code for the population data.

Click here to reveal the code.

Now let’s take a look at the data:

Rows: 27,758
Columns: 6
$ BUYER_COUNTY <chr> "ABBEVILLE", "ABBEVILLE", "ABBEVILLE", "ABBEVILLE", "ABB…
$ BUYER_STATE  <chr> "SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC", "L…
$ year         <int> 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 20…
$ count        <int> 877, 908, 871, 930, 1197, 1327, 1509, 1572, 1558, 5802, …
$ DOSAGE_UNIT  <dbl> 363620, 402940, 424590, 467230, 539280, 566560, 589010, …
$ countyfips   <chr> "45001", "45001", "45001", "45001", "45001", "45001", "4…
# A tibble: 9 x 1
   year
  <int>
1  2006
2  2007
3  2008
4  2009
5  2010
6  2011
7  2012
8  2013
9  2014

Looks like we have the same years of data.

Data Exploration


Now let’s take a deaper look at the data to see if we have any missing data using the naniar package.

We can use the vis_miss() function to create a plot of missing data.

Let’s start with the land area data.

Looks like there is no missing data.

How about the population data:

We appear to be missing some values for the Name and variable data, but we don`t intend to use these, so this should be ok. It is however a good idea to check these rows to see if anything strange is happening.

Let’s use the filter() function of the dplyr package and the is.na() base function to see more about the data that does not have countyfips codes.

We will also start using the %>% pipe of the magrittr package for our assignments.

Click here if you are unfamiliar with piping in R, which uses this %>% operator

By piping we mean using the %>% pipe operator which is accessible after loading the tidyverse or several of the packages within the tidyverse like dplyr because they load the magrittr package. This allows us to perform multiple sequential steps on one data input.


# A tibble: 15 x 10
   BUYER_COUNTY BUYER_STATE countyfips STATE COUNTY county_name NAME  variable
   <chr>        <chr>       <chr>      <int>  <int> <chr>       <chr> <chr>   
 1 PRINCE OF W… AK          02198          2    201 Prince of … <NA>  <NA>    
 2 SKAGWAY HOO… AK          02232          2    232 Skagway Ho… <NA>  <NA>    
 3 WRANGELL     AK          02275          2    280 Wrangell    <NA>  <NA>    
 4 PRINCE OF W… AK          02198          2    201 Prince of … <NA>  <NA>    
 5 SKAGWAY HOO… AK          02232          2    232 Skagway Ho… <NA>  <NA>    
 6 WRANGELL     AK          02275          2    280 Wrangell    <NA>  <NA>    
 7 PRINCE OF W… AK          02198          2    201 Prince of … <NA>  <NA>    
 8 SKAGWAY HOO… AK          02232          2    232 Skagway Ho… <NA>  <NA>    
 9 WRANGELL     AK          02275          2    280 Wrangell    <NA>  <NA>    
10 SKAGWAY HOO… AK          02232          2    232 Skagway Ho… <NA>  <NA>    
11 SKAGWAY HOO… AK          02232          2    232 Skagway Ho… <NA>  <NA>    
12 SKAGWAY HOO… AK          02232          2    232 Skagway Ho… <NA>  <NA>    
13 SKAGWAY HOO… AK          02232          2    232 Skagway Ho… <NA>  <NA>    
14 SKAGWAY HOO… AK          02232          2    232 Skagway Ho… <NA>  <NA>    
15 SKAGWAY HOO… AK          02232          2    232 Skagway Ho… <NA>  <NA>    
# … with 2 more variables: year <int>, population <int>

This looks ok. So let’s now move on to the DEA data.

Interesting, we appear to be missing countyfips codes for a small percentage of our annual data.

Let’s take a look at this data:

# A tibble: 760 x 6
   BUYER_COUNTY BUYER_STATE  year count DOSAGE_UNIT countyfips
   <chr>        <chr>       <int> <int>       <dbl> <chr>     
 1 ADJUNTAS     PR           2006   147      102800 <NA>      
 2 ADJUNTAS     PR           2007   153      104800 <NA>      
 3 ADJUNTAS     PR           2008   153       45400 <NA>      
 4 ADJUNTAS     PR           2009   184       54200 <NA>      
 5 ADJUNTAS     PR           2010   190       56200 <NA>      
 6 ADJUNTAS     PR           2011   186       65530 <NA>      
 7 ADJUNTAS     PR           2012   138       57330 <NA>      
 8 ADJUNTAS     PR           2013   138       65820 <NA>      
 9 ADJUNTAS     PR           2014    90       59490 <NA>      
10 AGUADA       PR           2006   160       49200 <NA>      
# … with 750 more rows

It looks like the missing data is data for Puerto Rico - it makes sense that it doesn’t have countyfips codes.

Let’s see if there is any data other than data for Puerto Rico that is also missing countyfips values. We can use the != operator which indicates not equal to.

# A tibble: 74 x 6
   BUYER_COUNTY             BUYER_STATE  year count DOSAGE_UNIT countyfips
   <chr>                    <chr>       <int> <int>       <dbl> <chr>     
 1 GUAM                     GU           2006   319      265348 <NA>      
 2 GUAM                     GU           2007   330      275600 <NA>      
 3 GUAM                     GU           2008   313      286900 <NA>      
 4 GUAM                     GU           2009   390      355300 <NA>      
 5 GUAM                     GU           2010   510      413800 <NA>      
 6 GUAM                     GU           2011   559      475600 <NA>      
 7 GUAM                     GU           2012   616      564800 <NA>      
 8 GUAM                     GU           2013   728      623200 <NA>      
 9 GUAM                     GU           2014   712      558960 <NA>      
10 MONTGOMERY               AR           2006   469      175390 <NA>      
11 MONTGOMERY               AR           2007   597      241270 <NA>      
12 MONTGOMERY               AR           2008   561      251760 <NA>      
13 MONTGOMERY               AR           2009   554      244160 <NA>      
14 MONTGOMERY               AR           2010   449      247990 <NA>      
15 MONTGOMERY               AR           2011   560      313800 <NA>      
16 MONTGOMERY               AR           2012   696      339520 <NA>      
17 MONTGOMERY               AR           2013   703      382300 <NA>      
18 MONTGOMERY               AR           2014   491      396900 <NA>      
19 NORTHERN MARIANA ISLANDS MP           2006   165      117850 <NA>      
20 NORTHERN MARIANA ISLANDS MP           2007   157      117500 <NA>      
21 NORTHERN MARIANA ISLANDS MP           2008   204      143000 <NA>      
22 NORTHERN MARIANA ISLANDS MP           2009   269      186900 <NA>      
23 NORTHERN MARIANA ISLANDS MP           2010   231      196360 <NA>      
24 NORTHERN MARIANA ISLANDS MP           2011   264      208500 <NA>      
25 NORTHERN MARIANA ISLANDS MP           2012   290      217400 <NA>      
26 NORTHERN MARIANA ISLANDS MP           2013   258      231400 <NA>      
27 NORTHERN MARIANA ISLANDS MP           2014   260      239200 <NA>      
28 PALAU                    PW           2006     5       14000 <NA>      
29 PALAU                    PW           2007     9       26600 <NA>      
30 PALAU                    PW           2008     2        7500 <NA>      
31 PALAU                    PW           2009     3       10000 <NA>      
32 PALAU                    PW           2013     1        1000 <NA>      
33 SAINT CROIX              VI           2006   544      198800 <NA>      
34 SAINT CROIX              VI           2007   612      237120 <NA>      
35 SAINT CROIX              VI           2008   694      254020 <NA>      
36 SAINT CROIX              VI           2009   601      233860 <NA>      
37 SAINT CROIX              VI           2010   764      316260 <NA>      
38 SAINT CROIX              VI           2011   756      320850 <NA>      
39 SAINT CROIX              VI           2012   755      314690 <NA>      
40 SAINT CROIX              VI           2013   802      328410 <NA>      
41 SAINT CROIX              VI           2014   684      269040 <NA>      
42 SAINT JOHN               VI           2006    65       22200 <NA>      
43 SAINT JOHN               VI           2007    60       21800 <NA>      
44 SAINT JOHN               VI           2008    70       24700 <NA>      
45 SAINT JOHN               VI           2009    58       23100 <NA>      
46 SAINT JOHN               VI           2010    75       23500 <NA>      
47 SAINT JOHN               VI           2011    89       30200 <NA>      
48 SAINT JOHN               VI           2012    85       30200 <NA>      
49 SAINT JOHN               VI           2013    66       22000 <NA>      
50 SAINT JOHN               VI           2014    63       20400 <NA>      
51 SAINT THOMAS             VI           2006   628      219100 <NA>      
52 SAINT THOMAS             VI           2007   757      249480 <NA>      
53 SAINT THOMAS             VI           2008   815      294250 <NA>      
54 SAINT THOMAS             VI           2009   798      313200 <NA>      
55 SAINT THOMAS             VI           2010   802      318630 <NA>      
56 SAINT THOMAS             VI           2011   932      383350 <NA>      
57 SAINT THOMAS             VI           2012   939      373280 <NA>      
58 SAINT THOMAS             VI           2013   988      376400 <NA>      
59 SAINT THOMAS             VI           2014  1021      314440 <NA>      
60 <NA>                     AE           2006     2         330 <NA>      
61 <NA>                     CA           2006    47       12600 <NA>      
62 <NA>                     CT           2006   305       78700 <NA>      
63 <NA>                     CT           2007   112       30900 <NA>      
64 <NA>                     CT           2008    48       15000 <NA>      
65 <NA>                     FL           2006     9         900 <NA>      
66 <NA>                     FL           2007     7         700 <NA>      
67 <NA>                     GA           2006   114       51700 <NA>      
68 <NA>                     IA           2006     7        2300 <NA>      
69 <NA>                     IN           2006   292       39300 <NA>      
70 <NA>                     MA           2006   247      114900 <NA>      
71 <NA>                     NV           2006   380      173600 <NA>      
72 <NA>                     NV           2007   447      200600 <NA>      
73 <NA>                     NV           2008     5        2200 <NA>      
74 <NA>                     OH           2006    23        5100 <NA>      

It looks like there is also data for other territories in the dataset, as well as some counties with no name.

For some reason the rows for the Montgomery county of Arkansa are also missing a countyfips value.

# A tibble: 9 x 6
  BUYER_COUNTY BUYER_STATE  year count DOSAGE_UNIT countyfips
  <chr>        <chr>       <int> <int>       <dbl> <chr>     
1 MONTGOMERY   AR           2006   469      175390 <NA>      
2 MONTGOMERY   AR           2007   597      241270 <NA>      
3 MONTGOMERY   AR           2008   561      251760 <NA>      
4 MONTGOMERY   AR           2009   554      244160 <NA>      
5 MONTGOMERY   AR           2010   449      247990 <NA>      
6 MONTGOMERY   AR           2011   560      313800 <NA>      
7 MONTGOMERY   AR           2012   696      339520 <NA>      
8 MONTGOMERY   AR           2013   703      382300 <NA>      
9 MONTGOMERY   AR           2014   491      396900 <NA>      

According to this website thie fIPS code is 05097.

We will update these values in the next section.

Data Wrangling


Cleaning land data

We want the LND110210D column which is the data from the year 2010.

LND = Land Area 110 = unit square miles (subgroup-code of the group) * avocado I found this somehwere else.. the census info was vauge would like to confirm that that is indeed what the sugroup code shows us 2 = century 10 = 2010 (based on the century) D = Data

Thus we can select just the county names, the county numeric codes, and the LND110210Dcolumn by using the select() function of the dplyr package.

# A tibble: 3,198 x 3
   Areaname      STCOU LND110210D
   <chr>         <chr>      <dbl>
 1 UNITED STATES 00000   3531905.
 2 ALABAMA       01000     50645.
 3 Autauga, AL   01001       594.
 4 Baldwin, AL   01003      1590.
 5 Barbour, AL   01005       885.
 6 Bibb, AL      01007       623.
 7 Blount, AL    01009       645.
 8 Bullock, AL   01011       623.
 9 Butler, AL    01013       777.
10 Calhoun, AL   01015       606.
# … with 3,188 more rows

Updating countyfips

We will use the case_when() function of the dplyr package recode the NA values for the rows for the MONGOMERY county of AR to be 05097. First we need to specify for these particular rows. Becuase there Montgomery may be a county name in other states, we need to evaluate when the BUYER_STATE is AR and when the BUYER_COUNTY is MONTGOMERY. We will use the & opperator to indcate that both conditions must be true. We will then recode the coutryfips values for these rows to be "05097" using the ~ symbol. All other values need to stay the same. Thus we need to use TRUE ~ to recode all the other countyfips values to what they currently are. Otherwise these would autmatically be NA.

We are also going to use a special pipe operator from the magrittr package called the compound assignment pipe-operator or sometimes the double pipe operator.

This allows us to use the annualDosage as our input and reassign it at the end after all the subsequent steps have been performed, although in this case it is only one step.

Now we can check that we indeed fixed our data.

# A tibble: 0 x 6
# … with 6 variables: BUYER_COUNTY <chr>, BUYER_STATE <chr>, year <int>,
#   count <int>, DOSAGE_UNIT <dbl>, countyfips <chr>
# A tibble: 9 x 6
  BUYER_COUNTY BUYER_STATE  year count DOSAGE_UNIT countyfips
  <chr>        <chr>       <int> <int>       <dbl> <chr>     
1 MONTGOMERY   AR           2006   469      175390 05097     
2 MONTGOMERY   AR           2007   597      241270 05097     
3 MONTGOMERY   AR           2008   561      251760 05097     
4 MONTGOMERY   AR           2009   554      244160 05097     
5 MONTGOMERY   AR           2010   449      247990 05097     
6 MONTGOMERY   AR           2011   560      313800 05097     
7 MONTGOMERY   AR           2012   696      339520 05097     
8 MONTGOMERY   AR           2013   703      382300 05097     
9 MONTGOMERY   AR           2014   491      396900 05097     

Great! We fixed it.

OK, we also had some rows that didn’t have county names because they were just missing or the data was for US territories. We will remove the values that dont have county names.

First let’s take a look at them agian.

# A tibble: 17 x 6
   BUYER_COUNTY BUYER_STATE  year count DOSAGE_UNIT countyfips
   <chr>        <chr>       <int> <int>       <dbl> <chr>     
 1 <NA>         AE           2006     2         330 <NA>      
 2 <NA>         CA           2006    47       12600 <NA>      
 3 <NA>         CT           2006   305       78700 <NA>      
 4 <NA>         CT           2007   112       30900 <NA>      
 5 <NA>         CT           2008    48       15000 <NA>      
 6 <NA>         FL           2006     9         900 <NA>      
 7 <NA>         FL           2007     7         700 <NA>      
 8 <NA>         GA           2006   114       51700 <NA>      
 9 <NA>         IA           2006     7        2300 <NA>      
10 <NA>         IN           2006   292       39300 <NA>      
11 <NA>         MA           2006   247      114900 <NA>      
12 <NA>         NV           2006   380      173600 <NA>      
13 <NA>         NV           2007   447      200600 <NA>      
14 <NA>         NV           2008     5        2200 <NA>      
15 <NA>         OH           2006    23        5100 <NA>      
16 <NA>         PR           2006    10       17800 <NA>      
17 <NA>         PR           2007     2        1300 <NA>      

We can filter out these values by using the ! exclamation mark before the is.na() function.

And now let’s check that these NA values are gone:

# A tibble: 0 x 6
# … with 6 variables: BUYER_COUNTY <chr>, BUYER_STATE <chr>, year <int>,
#   count <int>, DOSAGE_UNIT <dbl>, countyfips <chr>

Let’s check if our land area data has information for US territories. If not, we will remove the data for the territories in our annualDosage data. However, this would be very interesting and imporatant to investigate. We can use the str_detect() function of the stringr package, which contains lots of functions for looking for patterns in character strings, to look for data from Puerto Rico.

The str_detect() function allows us to look for a particular pattern. It does not have to be the full value, there can be a partial match. Thus we can look to see if there are any PR strings withing the vlaues of the the Areaname variable.

# A tibble: 0 x 3
# … with 3 variables: Areaname <chr>, STCOU <chr>, LND110210D <dbl>

You can see using a different abbreviation, that this code does as intended:

# A tibble: 81 x 3
   Areaname     STCOU LND110210D
   <chr>        <chr>      <dbl>
 1 ARIZONA      04000    113594.
 2 ARKANSAS     05000     52035.
 3 Arkansas, AR 05001       989.
 4 Ashley, AR   05003       925.
 5 Baxter, AR   05005       554.
 6 Benton, AR   05007       847.
 7 Boone, AR    05009       590.
 8 Bradley, AR  05011       649.
 9 Calhoun, AR  05013       629.
10 Carroll, AR  05015       630.
# … with 71 more rows

OK, so it does mot look like there is any territory land area data in this dataset. Thus we will also remove these from the annualDosage and monthlyDosage tibbles.

Question Opportunity

Do you recall how to do this?

Click here to reveal the code.

Great! Now there is no missing data in our annual data.

Rural and Urban Counties

Defining if a region is rural or urban is actually quite complicated as the overall population changes, the structure of our towns and cities changes, and the access between different locations changes over time. Please see this report form the US Census Beureau about the history of this definition.

According to several definitions - urban areas are often defined as those with greater than 50,000 people. However, there are also definitions of rural areas being based on “population densities of less than 500 people per square mile and places with fewer than 2,500 people”. Typically counties are made up of multiple areas.

The census estimates rural and urban areas around the US relatively often. However, census collections about these measuresments does not occur every year.

Thus we will define a county as rural or urban based on the population density using the USDA definition that we described above:

rural = population densities of less than 500 people per square mile, as well as places with fewer than 2,500 people
uban = populations densities of greater than 500 people per square mile

Ideally we would want land area from each year, as these do fluctuate a bit, however, this should be a decent approximation as 2010 is in the middle of our time span.

We will therefore calculate the density as the number of people per square mile by dividing the population values by the land area values. To do so we first need to combine our county_area and our county_pop data together. First we want to make sure that we have one column, in our case the column that contains the numeric code for the counties, in the same format and with the same name in both the tibbles that we wish to combine.

We can use the rename() function of the dplyr package to rename the STCOU column to be countyfips. The new name is always listed first before the old name with this function like so: rename(new_name = old_name).

We can use the mutate() funtion of the dplyr package to make the countyfips variable a factor in both tibbles.

What exactly is a factor?


Click here for an explanation of data classes in R

There are several classes of data in R programming. Character is one of these classes. A character string is an individual data value made up of characters. This can be a paragraph, like the legend for the table, or it can be a single letter or number like the letter "a" or the number "3".

If data are of class character, than the numeric values will not be processed like a numeric value in a mathematical sense.

If you want your numeric values to be interpreted that way, they need to be converted to a numeric class. The options typically used are integer (which has no decimal place) and double precision (which has a decimal place).

A variable that is a factor has a set of particular values called levels. Even if these are numeric, they will be interpreted as level not as a mathematical numnber. You can modify the order of these levels with the forcats package.


Great! Now we are ready to combine our data together.

We can do so using one of the *_join()functions of the dplyr package.

There are several ways to join data using the dplyr package.

[source]

Here is a visualization of these options:

[source]

See here for more details about joining data.

Since the population data came from the API, we probably have information about opioid pill shipments for each of the included counties. Since the land area data came from a different source, it may contain additional counties that are not in our population or drug shipment data. Thus we will use the left_join() function where x in this case will be the county_pop and y will be the country_area. Thus we will add the LND110210D (land area) values for all counties that match county_pop based on the countyfips column that they have in common.

We are now ready to calculate the population density per square mile. We can create a new column with this data using the mutate() function and the / to divide the population value by the land area value (in square miles) for each county. Let’s also make the year variable a factor.

Rows: 28,265
Columns: 13
$ BUYER_COUNTY <chr> "AUTAUGA", "BALDWIN", "BARBOUR", "BIBB", "BLOUNT", "BULL…
$ BUYER_STATE  <chr> "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "A…
$ countyfips   <fct> 01001, 01003, 01005, 01007, 01009, 01011, 01013, 01015, …
$ STATE        <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ COUNTY       <int> 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 3…
$ county_name  <chr> "Autauga", "Baldwin", "Barbour", "Bibb", "Blount", "Bull…
$ NAME         <chr> "Autauga County, Alabama", "Baldwin County, Alabama", "B…
$ variable     <chr> "B01003_001", "B01003_001", "B01003_001", "B01003_001", …
$ year         <fct> 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2006, 20…
$ population   <int> 51328, 168121, 27861, 22099, 55485, 10776, 20815, 115388…
$ Areaname     <chr> "Autauga, AL", "Baldwin, AL", "Barbour, AL", "Bibb, AL",…
$ LND110210D   <dbl> 594.44, 1589.78, 884.88, 622.58, 644.78, 622.81, 776.83,…
$ density      <dbl> 86.34681, 105.75111, 31.48563, 35.49584, 86.05261, 17.30…

Great, now we are ready to create a variable that classifies if a county was rural or urban based on our definition of rural counties being those with less than 500 people per square mile as well as those with less than 2,500 people. We will use the case_when() function of the dplyr package to calssify the new rural_urban variable as either "Urban" or "Rural" based on the evaluations of the density and the population variables. If the density is greater than or equal to 500 people per square mile, then the county will be coded as "Urban", alternatively if the density is less than 500 people per square mile or the population is less than 2500, than the county will be coded as "Rural". The | opperator is used to indicate that either expression should result in coding the county as "Rural"

We can use the count() function of the dplyr package to see how many of each this resulted in:

# A tibble: 2 x 2
  rural_urban     n
  <chr>       <int>
1 Rural       26065
2 Urban        2200

We will now combine the annualDosage data with the count_info tibble.

Question Opportunity

How might we do this?

Click here to reveal the code.

Rows: 27,007
Columns: 16
$ BUYER_COUNTY <chr> "ABBEVILLE", "ABBEVILLE", "ABBEVILLE", "ABBEVILLE", "ABB…
$ BUYER_STATE  <chr> "SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC", "L…
$ year         <fct> 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 20…
$ count        <int> 877, 908, 871, 930, 1197, 1327, 1509, 1572, 1558, 5802, …
$ DOSAGE_UNIT  <dbl> 363620, 402940, 424590, 467230, 539280, 566560, 589010, …
$ countyfips   <fct> 45001, 45001, 45001, 45001, 45001, 45001, 45001, 45001, …
$ STATE        <int> 45, 45, 45, 45, 45, 45, 45, 45, 45, 22, 22, 22, 22, 22, …
$ COUNTY       <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ county_name  <chr> "Abbeville", "Abbeville", "Abbeville", "Abbeville", "Abb…
$ NAME         <chr> "Abbeville County, South Carolina", "Abbeville County, S…
$ variable     <chr> "B01003_001", "B01003_001", "B01003_001", "B01003_001", …
$ population   <int> 25821, 25745, 25699, 25347, 25643, 25515, 25387, 25233, …
$ Areaname     <chr> "Abbeville, SC", "Abbeville, SC", "Abbeville, SC", "Abbe…
$ LND110210D   <dbl> 490.48, 490.48, 490.48, 490.48, 490.48, 490.48, 490.48, …
$ density      <dbl> 52.64435, 52.48940, 52.39561, 51.67795, 52.28144, 52.020…
$ rural_urban  <chr> "Rural", "Rural", "Rural", "Rural", "Rural", "Rural", "R…

Great, now we should have the data that we need for the case study.

Notice how there is a variable called DOSAGE_UNIT. This indicates the number of pills shipped to a pharmacy in this county that were either oxycodone or hydrocodone.

Let’s do a check to see how complete our data is now that we have combined our country_info data with the monthlyDosage and annualDosage data. We will have NA values for any counties present in the DAE data but not in our land area data. We can use the vis_miss() function naniar package to create a plot that shows if we have any missing data.

# A tibble: 27 x 16
   BUYER_COUNTY BUYER_STATE year  count DOSAGE_UNIT countyfips STATE COUNTY
   <chr>        <chr>       <fct> <int>       <dbl> <fct>      <int>  <int>
 1 MONTGOMERY   AR          2006    469      175390 05097         NA     NA
 2 MONTGOMERY   AR          2007    597      241270 05097         NA     NA
 3 MONTGOMERY   AR          2008    561      251760 05097         NA     NA
 4 MONTGOMERY   AR          2009    554      244160 05097         NA     NA
 5 MONTGOMERY   AR          2010    449      247990 05097         NA     NA
 6 MONTGOMERY   AR          2011    560      313800 05097         NA     NA
 7 MONTGOMERY   AR          2012    696      339520 05097         NA     NA
 8 MONTGOMERY   AR          2013    703      382300 05097         NA     NA
 9 MONTGOMERY   AR          2014    491      396900 05097         NA     NA
10 PRINCE OF W… AK          2006    190       62700 02201         NA     NA
# … with 17 more rows, and 8 more variables: county_name <chr>, NAME <chr>,
#   variable <chr>, population <int>, Areaname <chr>, LND110210D <dbl>,
#   density <dbl>, rural_urban <chr>

There does not appear to be land area and/or population data for these counties.

# A tibble: 9 x 14
  BUYER_COUNTY BUYER_STATE countyfips STATE COUNTY county_name NAME  variable
  <chr>        <chr>       <fct>      <int>  <int> <chr>       <chr> <chr>   
1 AUTAUGA      AL          01001          1      1 Autauga     Auta… B01003_…
2 AUTAUGA      AL          01001          1      1 Autauga     Auta… B01003_…
3 AUTAUGA      AL          01001          1      1 Autauga     Auta… B01003_…
4 AUTAUGA      AL          01001          1      1 Autauga     Auta… B01003_…
5 AUTAUGA      AL          01001          1      1 Autauga     Auta… B01003_…
6 AUTAUGA      AL          01001          1      1 Autauga     Auta… B01003_…
7 AUTAUGA      AL          01001          1      1 Autauga     Auta… B01003_…
8 AUTAUGA      AL          01001          1      1 Autauga     Auta… B01003_…
9 AUTAUGA      AL          01001          1      1 Autauga     Auta… B01003_…
# … with 6 more variables: year <fct>, population <int>, Areaname <chr>,
#   LND110210D <dbl>, density <dbl>, rural_urban <chr>
# A tibble: 0 x 14
# … with 14 variables: BUYER_COUNTY <chr>, BUYER_STATE <chr>, countyfips <fct>,
#   STATE <int>, COUNTY <int>, county_name <chr>, NAME <chr>, variable <chr>,
#   year <fct>, population <int>, Areaname <chr>, LND110210D <dbl>,
#   density <dbl>, rural_urban <chr>
# A tibble: 0 x 14
# … with 14 variables: BUYER_COUNTY <chr>, BUYER_STATE <chr>, countyfips <fct>,
#   STATE <int>, COUNTY <int>, county_name <chr>, NAME <chr>, variable <chr>,
#   year <fct>, population <int>, Areaname <chr>, LND110210D <dbl>,
#   density <dbl>, rural_urban <chr>
# A tibble: 0 x 14
# … with 14 variables: BUYER_COUNTY <chr>, BUYER_STATE <chr>, countyfips <fct>,
#   STATE <int>, COUNTY <int>, county_name <chr>, NAME <chr>, variable <chr>,
#   year <fct>, population <int>, Areaname <chr>, LND110210D <dbl>,
#   density <dbl>, rural_urban <chr>
# A tibble: 1 x 34
  Areaname STCOU LND010190F LND010190D LND010190N1 LND010190N2 LND010200F
  <chr>    <chr>      <dbl>      <dbl> <chr>       <chr>            <dbl>
1 Montgom… 05097          0       800. 0000        0000                 0
# … with 27 more variables: LND010200D <dbl>, LND010200N1 <chr>,
#   LND010200N2 <chr>, LND110180F <dbl>, LND110180D <dbl>, LND110180N1 <chr>,
#   LND110180N2 <chr>, LND110190F <dbl>, LND110190D <dbl>, LND110190N1 <chr>,
#   LND110190N2 <chr>, LND110200F <dbl>, LND110200D <dbl>, LND110200N1 <chr>,
#   LND110200N2 <chr>, LND110210F <dbl>, LND110210D <dbl>, LND110210N1 <chr>,
#   LND110210N2 <chr>, LND210190F <dbl>, LND210190D <dbl>, LND210190N1 <chr>,
#   LND210190N2 <chr>, LND210200F <dbl>, LND210200D <dbl>, LND210200N1 <chr>,
#   LND210200N2 <chr>
# A tibble: 0 x 34
# … with 34 variables: Areaname <chr>, STCOU <chr>, LND010190F <dbl>,
#   LND010190D <dbl>, LND010190N1 <chr>, LND010190N2 <chr>, LND010200F <dbl>,
#   LND010200D <dbl>, LND010200N1 <chr>, LND010200N2 <chr>, LND110180F <dbl>,
#   LND110180D <dbl>, LND110180N1 <chr>, LND110180N2 <chr>, LND110190F <dbl>,
#   LND110190D <dbl>, LND110190N1 <chr>, LND110190N2 <chr>, LND110200F <dbl>,
#   LND110200D <dbl>, LND110200N1 <chr>, LND110200N2 <chr>, LND110210F <dbl>,
#   LND110210D <dbl>, LND110210N1 <chr>, LND110210N2 <chr>, LND210190F <dbl>,
#   LND210190D <dbl>, LND210190N1 <chr>, LND210190N2 <chr>, LND210200F <dbl>,
#   LND210200D <dbl>, LND210200N1 <chr>, LND210200N2 <chr>
# A tibble: 0 x 34
# … with 34 variables: Areaname <chr>, STCOU <chr>, LND010190F <dbl>,
#   LND010190D <dbl>, LND010190N1 <chr>, LND010190N2 <chr>, LND010200F <dbl>,
#   LND010200D <dbl>, LND010200N1 <chr>, LND010200N2 <chr>, LND110180F <dbl>,
#   LND110180D <dbl>, LND110180N1 <chr>, LND110180N2 <chr>, LND110190F <dbl>,
#   LND110190D <dbl>, LND110190N1 <chr>, LND110190N2 <chr>, LND110200F <dbl>,
#   LND110200D <dbl>, LND110200N1 <chr>, LND110200N2 <chr>, LND110210F <dbl>,
#   LND110210D <dbl>, LND110210N1 <chr>, LND110210N2 <chr>, LND210190F <dbl>,
#   LND210190D <dbl>, LND210190N1 <chr>, LND210190N2 <chr>, LND210200F <dbl>,
#   LND210200D <dbl>, LND210200N1 <chr>, LND210200N2 <chr>
# A tibble: 0 x 10
# … with 10 variables: BUYER_COUNTY <chr>, BUYER_STATE <chr>, countyfips <fct>,
#   STATE <int>, COUNTY <int>, county_name <chr>, NAME <chr>, variable <chr>,
#   year <int>, population <int>
# A tibble: 0 x 10
# … with 10 variables: BUYER_COUNTY <chr>, BUYER_STATE <chr>, countyfips <fct>,
#   STATE <int>, COUNTY <int>, county_name <chr>, NAME <chr>, variable <chr>,
#   year <int>, population <int>
# A tibble: 0 x 10
# … with 10 variables: BUYER_COUNTY <chr>, BUYER_STATE <chr>, countyfips <fct>,
#   STATE <int>, COUNTY <int>, county_name <chr>, NAME <chr>, variable <chr>,
#   year <int>, population <int>

We will now remove these rows before further analysis:

Question Opportunity

Do you recall how you would do this?

Click here to reveal the code.

Nice! Now we have no missing data.

Data Analysis and Visualization


How have the number of rural and urban areas changed over years?

It looks as though the number of urban areas has increased, while the number of rural areas has decreased over time.

year Rural Urban Rural Change Urban Change percent_urban
2006 2903 239 NA NA 7.6
2007 2900 242 -3 3 7.7
2008 2900 242 0 0 7.7
2009 2900 240 0 -2 7.6
2010 2898 242 -2 2 7.7
2011 2893 247 -5 5 7.9
2012 2893 247 0 0 7.9
2013 2890 250 -3 3 8.0
2014 2888 251 -2 1 8.0
year Rural Urban Rural Change Urban Change percent_urban
2006 2903 239 NA NA 7.6
2007 2900 242 -3 3 7.7
2008 2900 242 0 0 7.7
2009 2900 240 0 -2 7.6
2010 2898 242 -2 2 7.7
2011 2893 247 -5 5 7.9
2012 2893 247 0 0 7.9
2013 2890 250 -3 3 8.0
2014 2888 251 -2 1 8.0

Pill shipments over time

In this plot it appearst that the counties in California got the largest number of pills shipped. However, since we did not account for population or population density, this could simply be because it is the most populated state. To account for this we will perform something called normalization to make a more fair comparison.

Normalization of pill count

Mormalization based on density

Rows: 26,980
Columns: 17
$ BUYER_COUNTY <chr> "ABBEVILLE", "ABBEVILLE", "ABBEVILLE", "ABBEVILLE", "ABB…
$ BUYER_STATE  <chr> "SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC", "L…
$ year         <fct> 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 20…
$ count        <int> 877, 908, 871, 930, 1197, 1327, 1509, 1572, 1558, 5802, …
$ DOSAGE_UNIT  <dbl> 363620, 402940, 424590, 467230, 539280, 566560, 589010, …
$ countyfips   <fct> 45001, 45001, 45001, 45001, 45001, 45001, 45001, 45001, …
$ STATE        <int> 45, 45, 45, 45, 45, 45, 45, 45, 45, 22, 22, 22, 22, 22, …
$ COUNTY       <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ county_name  <chr> "Abbeville", "Abbeville", "Abbeville", "Abbeville", "Abb…
$ NAME         <chr> "Abbeville County, South Carolina", "Abbeville County, S…
$ variable     <chr> "B01003_001", "B01003_001", "B01003_001", "B01003_001", …
$ population   <int> 25821, 25745, 25699, 25347, 25643, 25515, 25387, 25233, …
$ Areaname     <chr> "Abbeville, SC", "Abbeville, SC", "Abbeville, SC", "Abbe…
$ LND110210D   <dbl> 490.48, 490.48, 490.48, 490.48, 490.48, 490.48, 490.48, …
$ density      <dbl> 52.64435, 52.48940, 52.39561, 51.67795, 52.28144, 52.020…
$ rural_urban  <chr> "Rural", "Rural", "Rural", "Rural", "Rural", "Rural", "R…
$ dens_DOSAGE  <dbl> 6907.104, 7676.598, 8103.541, 9041.187, 10314.942, 10891…

Why Density Normalization?

Description about how we also need log transformation

Rows: 53,960
Columns: 17
$ BUYER_COUNTY <chr> "ABBEVILLE", "ABBEVILLE", "ABBEVILLE", "ABBEVILLE", "ABB…
$ BUYER_STATE  <chr> "SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC", "S…
$ year         <fct> 2006, 2006, 2007, 2007, 2008, 2008, 2009, 2009, 2010, 20…
$ count        <int> 877, 877, 908, 908, 871, 871, 930, 930, 1197, 1197, 1327…
$ countyfips   <fct> 45001, 45001, 45001, 45001, 45001, 45001, 45001, 45001, …
$ STATE        <int> 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, …
$ COUNTY       <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ county_name  <chr> "Abbeville", "Abbeville", "Abbeville", "Abbeville", "Abb…
$ NAME         <chr> "Abbeville County, South Carolina", "Abbeville County, S…
$ variable     <chr> "B01003_001", "B01003_001", "B01003_001", "B01003_001", …
$ population   <int> 25821, 25821, 25745, 25745, 25699, 25699, 25347, 25347, …
$ Areaname     <chr> "Abbeville, SC", "Abbeville, SC", "Abbeville, SC", "Abbe…
$ LND110210D   <dbl> 490.48, 490.48, 490.48, 490.48, 490.48, 490.48, 490.48, …
$ density      <dbl> 52.64435, 52.64435, 52.48940, 52.48940, 52.39561, 52.395…
$ rural_urban  <chr> "Rural", "Rural", "Rural", "Rural", "Rural", "Rural", "R…
$ type         <fct> DOSAGE_UNIT, dens_DOSAGE, DOSAGE_UNIT, dens_DOSAGE, DOSA…
$ value        <dbl> 363620.000, 6907.104, 402940.000, 7676.598, 424590.000, …

t-test

http://www.sthda.com/english/wiki/unpaired-two-samples-t-test-in-r


    Two Sample t-test

data:  DOSAGE_UNIT by rural_urban
t = -99.117, df = 26978, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -17804308 -17113799
sample estimates:
mean in group Rural mean in group Urban 
            2235774            19694828 

    Two Sample t-test

data:  dens_DOSAGE by rural_urban
t = 14.652, df = 26978, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 19978.13 26148.72
sample estimates:
mean in group Rural mean in group Urban 
           39031.93            15968.51 

We can see that the result is different depending on how we normalize the data!

Summary


Summary Plot

Synopsis

In this case study we have demonstrated the basics of R Markdown and how to create a dashboard with using the flexdashboard package. We also demonstrated how to include an interactive table with the DT package, how to include interactive plots using functions of the shiny package such as renderPlot(). We also included interactive value boxes using the renderValueBox() function of the flexdashboard package which works with the shiny package. Finally we also showed how to include interactive maps using the leaflet package.

This case study also explored how to properly calculate and interpret percentages when the data has missing values. We also discussed the benefits and limiting aspects of pie charts (using ggplot2) and waffle plots (using waffle).

Overall the dashboard that we created shows that the number of shootings per year has increased overtime. Further investigation is necessary to determine if this is simply due to increases in population alone or if the rate has increased due to other factors and if so, what those factors might be. It is also clear that the number of shootings and the number of deaths per capita varies by state. Thus there appears to be other aspects accounting for state differences.

Suggested Homework


Create another dashboard with graphs and statistics featuring other elements within this dataset. For example, students may create graphs that explore what school events are reported to have more shootings.

Additional Information


Session Info

R version 4.0.1 (2020-06-06)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Mojave 10.14.5

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] gdtools_0.2.2       formattable_0.2.0.1 ggpubr_0.4.0       
 [4] ggiraph_0.7.8       ggpol_0.0.6         ggplot2_3.3.1      
 [7] naniar_0.5.1        tidyr_1.1.0         dplyr_1.0.0        
[10] magrittr_1.5        readr_1.3.1         stringr_1.4.0      
[13] jsonlite_1.7.1      httr_1.4.2          tibble_3.0.1       
[16] readxl_1.3.1        knitr_1.28          here_0.1           

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.4.6      lattice_0.20-41   assertthat_0.2.1  rprojroot_1.3-2  
 [5] digest_0.6.25     utf8_1.1.4        R6_2.4.1          cellranger_1.1.0 
 [9] plyr_1.8.6        backports_1.1.7   visdat_0.5.3      evaluate_0.14    
[13] pillar_1.4.4      rlang_0.4.6       curl_4.3          uuid_0.1-4       
[17] data.table_1.12.8 car_3.0-8         Matrix_1.2-18     rmarkdown_2.2    
[21] splines_4.0.1     labeling_0.3      foreign_0.8-80    htmlwidgets_1.5.1
[25] munsell_0.5.0     broom_0.5.6       compiler_4.0.1    xfun_0.14        
[29] pkgconfig_2.0.3   systemfonts_0.2.2 base64enc_0.1-3   mgcv_1.8-31      
[33] htmltools_0.4.0   tidyselect_1.1.0  rio_0.5.16        viridisLite_0.3.0
[37] fansi_0.4.1       crayon_1.3.4      withr_2.2.0       grid_4.0.1       
[41] nlme_3.1-148      gtable_0.3.0      lifecycle_0.2.0   scales_1.1.1     
[45] zip_2.0.4         cli_2.0.2         stringi_1.4.6     carData_3.0-4    
[49] farver_2.0.3      ggsignif_0.6.0    ellipsis_0.3.1    generics_0.0.2   
[53] vctrs_0.3.1       cowplot_1.0.0     openxlsx_4.1.5    tools_4.0.1      
[57] forcats_0.5.0     glue_1.4.1        purrr_0.3.4       hms_0.5.3        
[61] abind_1.4-5       yaml_2.2.1        usdata_0.1.0      colorspace_1.4-1 
[65] rstatix_0.6.0     haven_2.3.1      

Acknowledgements

We would like to acknowledge Elizabeth Stuart for assisting in framing the major direction of the case study.

We would also like to acknowledge the Bloomberg American Health Initiative for funding this work.

LS0tCnRpdGxlOiAiT3Bpb2RzIGluIFVuaXRlZCBTdGF0ZXMiCmNzczogc3R5bGUuY3NzCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgc2VsZl9jb250YWluZWQ6IHllcwogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vCiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogeWVzCgotLS0KCjxzdHlsZT4KI1RPQyB7CiAgYmFja2dyb3VuZDogdXJsKCJodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vaW1nL2xvZ28uanBnIik7CiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOwogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50OwogIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7Cn0KPC9zdHlsZT4KCgo8IS0tIE9wZW4gYWxsIGxpbmtzIGluIG5ldyB0YWItLT4gIAo8YmFzZSB0YXJnZXQ9Il9ibGFuayIvPiAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgY2FjaGUgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBvdXQud2lkdGggPSAnOTAlJykKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGtuaXRyKQpgYGAKCiMjIyMgey5vdXRsaW5lIH0KYGBge3IsIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmUoImltZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFQSS5wbmciKSkKYGBgCiMjIyMKCiMjIyMgey5kaXNjbGFpbWVyX2Jsb2NrfQoKKipEaXNjbGFpbWVyKio6IFRoZSBwdXJwb3NlIG9mIHRoZSBbT3BlbiBDYXNlIFN0dWRpZXNdKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pbyl7dGFyZ2V0PSJfYmxhbmsifSBwcm9qZWN0IGlzICoqdG8gZGVtb25zdHJhdGUgdGhlIHVzZSBvZiB2YXJpb3VzIGRhdGEgc2NpZW5jZSBtZXRob2RzLCB0b29scywgYW5kIHNvZnR3YXJlIGluIHRoZSBjb250ZXh0IG9mIG1lc3N5LCByZWFsLXdvcmxkIGRhdGEqKi4gQSBnaXZlbiBjYXNlIHN0dWR5IGRvZXMgbm90IGNvdmVyIGFsbCBhc3BlY3RzIG9mIHRoZSByZXNlYXJjaCBwcm9jZXNzLCBpcyBub3QgY2xhaW1pbmcgdG8gYmUgdGhlIG1vc3QgYXBwcm9wcmlhdGUgd2F5IHRvIGFuYWx5emUgYSBnaXZlbiBkYXRhIHNldCwgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBpbiB0aGUgY29udGV4dCBvZiBtYWtpbmcgcG9saWN5IGRlY2lzaW9ucyB3aXRob3V0IGV4dGVybmFsIGNvbnN1bHRhdGlvbiBmcm9tIHNjaWVudGlmaWMgZXhwZXJ0cy4gCgojIyMjCgojIyMjIHsubGljZW5zZV9ibG9ja30KClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBbKENDIEJZLU5DIDMuMCldKGh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvdXMvKXt0YXJnZXQ9Il9ibGFuayJ9IFVuaXRlZCBTdGF0ZXMgTGljZW5zZS4KCiMjIyMKCiMjIyMgey5yZWZlcmVuY2VfYmxvY2t9CgpUbyBjaXRlIHRoaXMgY2FzZSBzdHVkeSBwbGVhc2UgdXNlOgoKV3JpZ2h0LCBDYXJyaWUsIGFuZCBPbnRpdmVyb3MsIE1pY2hhZWwgYW5kIEphZ2VyLCBMZWFoIGFuZCBUYXViLCBNYXJnYXJldCBhbmQgSGlja3MsIFN0ZXBoYW5pZS4gKDIwMjApLiBodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vb2NzLWJwLW9waW9pZC1ydXJhbC11cmJhbi9vY3NfcG9wLmh0bWwuIE9waW9pZHMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgKFZlcnNpb24gdjEuMC4wKS4KCmF2b2NhZG8gdXBkYXRlIHVybAojIyMjCgojICoqTW90aXZhdGlvbioqCioqKiAKCgpJbiB0aGlzIGNhc2Ugc3R1ZHkgd2Ugd2lsbCBiZSBleGFtaW5pbmcgdGhlIG51bWJlciBvZiBvcGlvaWQgcGlsbHMgKHNwZWNpZmljYWxseSBbb3h5Y29kb25lXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9PcGlvaWRfZXBpZGVtaWNfaW5fdGhlX1VuaXRlZF9TdGF0ZXMpIGFuZCBbaHlkcm9jb2RvbmVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL09waW9pZF9lcGlkZW1pY19pbl90aGVfVW5pdGVkX1N0YXRlcyksIGFzIHRoZXkgYXJlIHRoZSB0b3AgdHdvIGFidXNlZCBvcGlvaWRzKSBzaGlwcGVkIHRvIHBoYXJtYWNpZXMgYW5kIHBhcmFjdGl0aW9uYWVycyBhdCB0aGUgY291bnR5LWxldmVsIGFyb3VuZCB0aGUgVW5pdGVkIFN0YXRlcyAoVVMpIGZyb20gMjAwNiB0byAyMDE0LgoKVGhpcyBkYXRhIGNvbWVzIGZyb20gdGhlIFtERUFdKGh0dHBzOi8vd3d3LmRlYS5nb3YvKSBbQXV0b21hdGVkIFJlcG9ydHMgYW5kIENvbnNvbGlkYXRlZCBPcmRlcmluZyBTeXN0ZW0gKEFSQ09TKV0oaHR0cHM6Ly93d3cuZGVhZGl2ZXJzaW9uLnVzZG9qLmdvdi9hcmNvcy9yZXRhaWxfZHJ1Z19zdW1tYXJ5LykgYW5kIHdhcyByZWxlYXNlZCBieSB0aGUgW1dhc2hpbmd0b24gUG9zdF0oaHR0cHM6Ly93d3cud2FzaGluZ3RvbnBvc3QuY29tLykgYWZ0ZXIgbGVnYWwgYWN0aW9uIGJ5IHRoZSBvd25lciBvZiB0aGUgW0NoYXJsZXN0b24gR2F6ZXR0ZS1NYWlsXShodHRwczovL3d3dy53dmdhemV0dGVtYWlsLmNvbS8pIGluIFdlc3QgVmlyZ2luaWEgYW5kIHRoZSBbV2FzaGluZ3RvbiBQb3N0XShodHRwczovL3d3dy53YXNoaW5ndG9ucG9zdC5jb20vKS4KCldlIHdpbGwgaW52ZXN0aWdhdGUgaG93IHRoZSBudW1iZXIgb2Ygc2hpcHBlZCBwaWxscyBjb21wYXJlcyBmb3IgcnVyYWwgYW5kIHVyYmFuIGNvdW50aWVzLiBUaGlzIGFuYWx5c2lzIHdpbGwgZGVtb25zdHJhdGUgaG93IGRpZmZlcmVudCByZWdpb25zIG9mIHRoZSBjb3VudHJ5IG1heSBoYXZlIGJlZW4gbW9yZSBhdCByaXNrIGZvciBvcGlvaWQgYWRkaWN0aW9uIGNyaXNlcyBkdWUgdG8gZGlmZmVyaW5nIHJhdGVzIG9mIG9waW9pZCBwcmVzY3JpcHRpb24gKHVzaW5nIHRoZSBudW1iZXIgb2YgcGlsbHMgYXMgYSBwcm94eSBmb3IgcGVyc2NyaXB0aW9uIHJhdGVzKS4gVGhpcyB3aWxsIGhlbHAgaW5mb3JtIHN0dWRlbnRzIGFib3V0IGhvdyBldmlkZW5jZS1iYXNlZCBpbnRlcnZlbnRpb24gZGVjaXNpb25zIGFyZSBtYWRlIGluIHRoaXMgYXJlYS4gIAoKVGhpcyBjYXNlIHN0dWR5IGlzIG1vdGl2YXRlZCBieSB0aGlzIFthcnRpY2xlXShodHRwczovL3d3dy5jZGMuZ292L21td3Ivdm9sdW1lcy82OC93ci9tbTY4MDJhMS5odG0/c19jaWQ9bW02ODAyYTFfdyk6CgojIyMjIHsucmVmZXJlbmNlX2Jsb2NrfQoKR2FyY8OtYSwgTS4gQy4gZXQgYWwuIE9waW9pZCBQcmVzY3JpYmluZyBSYXRlcyBpbiBOb25tZXRyb3BvbGl0YW4gYW5kIE1ldHJvcG9saXRhbiBDb3VudGllcyBBbW9uZyBQcmltYXJ5IENhcmUgUHJvdmlkZXJzIFVzaW5nIGFuIEVsZWN0cm9uaWMgSGVhbHRoIFJlY29yZCBTeXN0ZW0g4oCUIFVuaXRlZCBTdGF0ZXMsIDIwMTTigJMyMDE3LiBNTVdSIE1vcmIuIE1vcnRhbC4gV2tseS4gUmVwLiA2OCwgMjXigJMzMCAoMjAxOSkuIERPSTogWzEwLjE1NTg1L21td3IubW02ODAyYTFdKGh0dHA6Ly9keC5kb2kub3JnLzEwLjE1NTg1L21td3IubW02ODAyYTEpCgojIyMjCgpUaGlzIGFydGljbGUgZXhwbG9yZXMgcmF0ZXMgb2Ygb3Bpb2lkIHBlcnNjcmlwdGlvbnMgaW4gcnVyYWwgYW5kIHVyYmFuIGNvbW11bnRpZXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgdXNpbmcgdGhlIFtBdGhlbmFoZWFsdGggZWxlY3Ryb25pYyBoZWFsdGggcmVjb3JkIChFSFIpIHN5c3RlbV0oaHR0cHM6Ly9sYW5kaW5nLmF0aGVuYWhlYWx0aC5jb20vZy9pbXByb3ZlY2FyZT9jbXA9MTA2NzI5NDEmdXRtX3NhbGVzZm9yY2U9NzAxNmYwMDAwMDF5V1FNQUEyJnV0bV9tZWRpdW09Y3BjJnV0bV9jYW1wYWlnbj0xJTIwQnJhbmRlZCUyMEV4cGVyaW1lbnRhbCZ1dG1fYWRncm91cD1Nb2RCcm9hZCZ1dG1fc291cmNlPWdvb2dsZSZ1dG1fdGVybT0lMkJhdGhlbmElMjAlMkJoZWFsdGgmdXRtX3R5cGU9YiZnY2xpZD1DajBLQ1Fqd3RaSDdCUkR6QVJJc0FHamJLMmJuX294eWQwak5CR1FrUE1jU1NwRXVHYnpMVXFMOG0tdHVBUVdNWi1zbVVOTExqdHp0QjdFYUFnU2xFQUx3X3djQikgZm9yIDMxLDQyMiBwcmltYXJ5IGNhcmUgcHJvdmlkZXJzIGZyb20gSmFudWFyeSAyMDE0IHRvIE1hcmNoIDIwMTcuCgpUaGUgbWFpbiB0YWtlYXdheXMgZnJvbSB0aGlzIGFydGljbGUgd2VyZToKCj4gQW1vbmcgNzAsMjM3IGZhdGFsIGRydWcgb3ZlcmRvc2VzIGluIDIwMTcsIHByZXNjcmlwdGlvbiBvcGlvaWRzIHdlcmUgaW52b2x2ZWQgaW4gMTcsMDI5ICgyNC4yJSkuCgo+IFRoZSBwZXJjZW50YWdlIG9mIHBhdGllbnRzIHByZXNjcmliZWQgYW4gb3Bpb2lkIHdhcyBoaWdoZXIgaW4gKipydXJhbCoqIHRoYW4gaW4gdXJiYW4gYXJlYXMuIAoKPiBIaWdoZXIgb3Bpb2lkIHByZXNjcmliaW5nIHJhdGVzIHB1dCBwYXRpZW50cyAqKmF0IHJpc2sgZm9yIGFkZGljdGlvbiBhbmQgb3ZlcmRvc2UqKi4KCgpJbmRlZWQsICB0aGlzIHdhcyBjb25maXJtZWQgYnkgYW5vdGhlciBbYXJ0aWNsZV0oaHR0cHM6Ly9qYW1hbmV0d29yay5jb20vam91cm5hbHMvamFtYXBzeWNoaWF0cnkvZnVsbGFydGljbGUvMTg3NDU3NSkgd2hpY2ggc3VydmV5ZWQgaGVyb2luIHVzZXJzLgoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KCkNpY2VybywgVC4gSi4sIEVsbGlzLCBNLiBTLiwgU3VycmF0dCwgSC4gTC4gJiBLdXJ0eiwgUy4gUC4gVGhlIENoYW5naW5nIEZhY2Ugb2YgSGVyb2luIFVzZSBpbiB0aGUgVW5pdGVkIFN0YXRlczogQSBSZXRyb3NwZWN0aXZlIEFuYWx5c2lzIG9mIHRoZSBQYXN0IDUwIFllYXJzLiBKQU1BIFBzeWNoaWF0cnkgNzEsIDgyMSAoMjAxNCkuIFtET0k6MTAuMTAwMS9qYW1hcHN5Y2hpYXRyeS4yMDE0LjM2Nl0oaHR0cHM6Ly9kb2kub3JnLzEwLjEwMDEvamFtYXBzeWNoaWF0cnkuMjAxNC4zNjYpCgojIyMjCgpUaGV5IGZvdW5kIHRoYXQ6Cgo+IFJlc3BvbmRlbnRzIHdobyBiZWdhbiB1c2luZyBoZXJvaW4gaW4gdGhlIDE5NjBzIHdlcmUgcHJlZG9taW5hbnRseSB5b3VuZyBtZW4gKDgyLjglOyBtZWFuIGFnZSwgMTYuNSB5ZWFycykgd2hvc2UgZmlyc3Qgb3Bpb2lkIG9mIGFidXNlIHdhcyBoZXJvaW4gKDgwJSkuCgo+IEhvd2V2ZXIsIG1vcmUgKipyZWNlbnQgdXNlcnMqKiB3ZXJlIG9sZGVyIChtZWFuIGFnZSwgMjIuOSB5ZWFycykgbWVuIGFuZCB3b21lbiAqKmxpdmluZyBpbiBsZXNzIHVyYmFuIGFyZWFzICg3NS4yJSkqKiB3aG8gd2VyZSAqKmludHJvZHVjZWQgdG8gb3Bpb2lkcyB0aHJvdWdoIHByZXNjcmlwdGlvbiBkcnVncyAoNzUuMCUpKiouCgo+IEhlcm9pbiB1c2UgaGFzIGNoYW5nZWQgZnJvbSBhbiBpbm5lci1jaXR5LCBtaW5vcml0eS1jZW50ZXJlZCBwcm9ibGVtIHRvIG9uZSB0aGF0IGhhcyBhIG1vcmUgd2lkZXNwcmVhZCBnZW9ncmFwaGljYWwgZGlzdHJpYnV0aW9uLCBpbnZvbHZpbmcgKipwcmltYXJpbHkgd2hpdGUgbWVuIGFuZCB3b21lbiBpbiB0aGVpciBsYXRlIDIwcyBsaXZpbmcgb3V0c2lkZSBvZiBsYXJnZSB1cmJhbiBhcmVhcyoqLgoKCmBgYHtyLCBvdXQud2lkdGggPSAiNTAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJqYW1lcy15YXJlbWEtNXR5TWdhZzB3Um8tdW5zcGxhc2guanBnIikpCmBgYAoKPHNwYW4+UGhvdG8gYnkgPGEgaHJlZj0iaHR0cHM6Ly91bnNwbGFzaC5jb20vQGphbWVzeWFyZW1hP3V0bV9zb3VyY2U9dW5zcGxhc2gmYW1wO3V0bV9tZWRpdW09cmVmZXJyYWwmYW1wO3V0bV9jb250ZW50PWNyZWRpdENvcHlUZXh0Ij5KYW1lcyBZYXJlbWE8L2E+IG9uIDxhIGhyZWY9Imh0dHBzOi8vdW5zcGxhc2guY29tL3MvcGhvdG9zL3BpbGxzP3V0bV9zb3VyY2U9dW5zcGxhc2gmYW1wO3V0bV9tZWRpdW09cmVmZXJyYWwmYW1wO3V0bV9jb250ZW50PWNyZWRpdENvcHlUZXh0Ij5VbnNwbGFzaDwvYT48L3NwYW4+CgojIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9iZXRhLnJzdHVkaW9jb25uZWN0LmNvbS9qamFsbGFpcmUvaHRtbHdpZGdldHMtaGlnaGNoYXJ0ZXIvKQoKCiMgKipNYWluIFF1ZXN0aW9ucyoqCioqKiAKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb246IDwvdT48L2I+CgogSG93IGRpZCBvcGlvaWQgc2hpcG1lbnQgcmF0ZXMgZGlmZmVyIGJldHdlZW4gcnVyYWwgYW5kIHVyYmFuIHJlZ2lvbnMgb3ZlciB0aW1lIGFyb3VuZCB0aGUgVVMgZnJvbSAyMDA2LTIwMTQ/CgoKIyMjIwoKIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKiAKKioqIAoKSW4gdGhpcyBjYXNlIHN0dWR5LCB3ZSB3aWxsIGRlbW9uc3RyYXRlIGhvdyB0byBvYnRhaW4gZGF0YSBmcm9tIGFuIFtBcHBsaWNhdGlvbiBQcm9ncmFtbWluZyBJbnRlcmZhY2UgKEFQSSldKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FQSSksIHdoaWNoIGlzIGFuIGludGVyZmFjZSB0aGF0IGFsbG93cyB1c2VycyB0byBtb3JlIGVhc2lseSBpbnRlcmFjdCB3aXRoIGEgZGF0YWJhc2UuIFdlIHdpbGwgYWxzbyBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW2BUaWR5dmVyc2VgXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSwgc3VjaCBhcyBgZHBseXJgLCBgdGlkeXJgLiBUaGUgdGlkeXZlcnNlIGlzIGEgbGlicmFyeSBvZiBwYWNrYWdlcyBjcmVhdGVkIGJ5IFJTdHVkaW8uIFdoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBtb3JlIGxlZ2libGUgYW5kIGludHVpdGl2ZS4KCgpgYGB7ciwgb3V0LndpZHRoID0gIjIwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKVGhlIHNraWxscywgbWV0aG9kcywgYW5kIGNvbmNlcHRzIHRoYXQgc3R1ZGVudHMgd2lsbCBiZSBmYW1pbGlhciB3aXRoIGJ5IHRoZSBlbmQgb2YgdGhpcyBjYXNlIHN0dWR5IGFyZToKCgpEYXRhIHNjaWVuY2Ugc2tpbGxzOiAgCiAgCjEuIEltcG9ydGluZyBkYXRhIGZyb20gYW4gW0FQSV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQVBJKSAoYGh0dHJgIGFuZCBgamFzb25saXRlYCkgIAoyLiBIb3cgdG8gcmVzaGFwZSBkYXRhIGJ5IHBpdm90aW5nIGJldHdlZW4gImxvbmciIGFuZCAid2lkZSIgZm9ybWF0cyBhbmQgZHJvcCByb3dzIHdpdGggYE5BYCB2YWx1ZXMgKGB0aWR5cmApIAozLiBIb3cgdG8gam9pbiBkYXRhIHdpdGggYGRwbHlyYAo0LiBIb3cgdG8gY3JlYXRlIGZvcm1hdHRlZCB0YWJsZXMgb2YgZGF0YSB3aXRoIGBmb3JtYXR0YWJsZWAKNS4gSG93IHRvIGNyZWF0ZSBkYXRhIHZpc3VhbGl6YXRpb25zIHdpdGggYGdncGxvdDJgIAo2LiBIb3cgdG8gbG9vayBmb3IgbWlzc2luZyBkYXRhIGluIGEgZGF0YXNldCAoYG5hbmlhcmApCgoKU3RhdGlzdGljYWwgY29uY2VwdHMgYW5kIG1ldGhvZHM6ICAKICAKMS4gVW5kZXJzdGFuZGluZyBvZiB3aGVuIGFuZCB3aHkgZGF0YSBub3JtYWxpemF0aW9uIGlzIHVzZWZ1bAoyLiBVbmRlcnN0YW5kaW5nIG9mIHdoZW4gYW5kIHdoeSBkYXRhIHRyYW5zZm9ybWF0aW9uIGlzIHVzZWZ1bAozLiBIb3cgdG8gaW1wbGVtZW50IGEgdC10ZXN0IGluIFIKNC4gSG93IHRvIGludGVycHRlIGEgdC10ZXN0IGluIFIKCioqKiAKCgpXZSB3aWxsIGJlZ2luIGJ5IGxvYWRpbmcgdGhlIHBhY2thZ2VzIHRoYXQgd2Ugd2lsbCBuZWVkOgoKCmBgYHtyfQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkoaHR0cikKbGlicmFyeShqc29ubGl0ZSkKbGlicmFyeShzdHJpbmdyKQoKCmxpYnJhcnkoaGVyZSkKbGlicmFyeShyZWFkcikKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKCmxpYnJhcnkobmFuaWFyKQpsaWJyYXJ5KGdncGxvdDIpCgpsaWJyYXJ5KGdncG9sKSAjY3JlYXRlcyBnZW9taml0dGVyCmxpYnJhcnkoZ2dpcmFwaCkgIyBjcmVhdGVzIGludGVyYWN0aXZlIHBsb3QgZm9yIHBsb3RzIHRoYXQgYXJlIGRpZmZpY3VsdCB0byBsYWJlbCBiZWNhdXNlIHRoZXkgaGF2ZSBzbyBtYW55IGVsZW1lbnRzCmxpYnJhcnkoZ2dwdWJyKSAjZ2dhcmFuZ2UgCgojIGxpYnJhcnkoZGV2dG9vbHMpCiMgbGlicmFyeSh1c2V0aGlzKQojIGxpYnJhcnkodGlkeXZlcnNlKQojIGxpYnJhcnkob3BlbmludHJvKQojICNsaWJyYXJ5KGFyY29zKQojIGxpYnJhcnkoZ2dpcmFwaCkKIyBsaWJyYXJ5KGdncHVicikKIyBsaWJyYXJ5KGdnZm9ydGlmeSkKIyBsaWJyYXJ5KGdncG9sKQojIGxpYnJhcnkobG1lNCkKbGlicmFyeShmb3JtYXR0YWJsZSkKCmBgYAoKCgogPHU+KipQYWNrYWdlcyB1c2VkIGluIHRoaXMgY2FzZSBzdHVkeToqKiA8L3U+CgpQYWNrYWdlICAgfCBVc2UgaW4gdGhpcyBjYXNlIHN0dWR5ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS0tLS0tLS0tIHwtLS0tLS0tLS0tLS0tCltoZXJlXShodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9oZXJlX2hlcmUpe3RhcmdldD0iX2JsYW5rIn0gICAgICAgfCB0byBlYXNpbHkgbG9hZCBhbmQgc2F2ZSBkYXRhICAKW3JlYWRyXShodHRwczovL3JlYWRyLnRpZHl2ZXJzZS5vcmcvKSB8ICB0byBpbXBvcnQgdGhlIGRhdGEgIGFzIGEgY3N2IGZpbGUgIApbdGliYmxlXShodHRwczovL3RpYmJsZS50aWR5dmVyc2Uub3JnLykgfCB0byBjcmVhdGUgdGliYmxlcyAodGhlIHRpZHl2ZXJzZSB2ZXJzaW9uIG9mIGRhdGFmcmFtZXMpCltkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZmlsdGVyLCBzdWJzZXQsIGpvaW4sIGFkZCByb3dzIHRvLCBhbmQgbW9kaWZ5IHRoZSBkYXRhICAKW3N0cmluZ3JdKGh0dHBzOi8vc3RyaW5nci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gbWFuaXB1bGF0ZSAgY2hhcmFjdGVyIHN0cmluZ3Mgd2l0aGluIHRoZSBkYXRhIChjb2xsYXBzaW5nIHN0cmluZ3MgdG9nZXRoZXIsIHJlcGxhY2UgdmFsdWVzLCBhbmQgZGV0ZWN0IHZhbHVlcykKW21hZ3JpdHRyXShodHRwczovL21hZ3JpdHRyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBwaXBlIHNlcXVlbnRpYWwgY29tbWFuZHMgClt0aWR5cl0oaHR0cHM6Ly90aWR5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gY2hhbmdlIHRoZSBzaGFwZSBvciBmb3JtYXQgb2YgdGliYmxlcyB0byB3aWRlIGFuZCBsb25nLCB0byBkcm9wIHJvd3Mgd2l0aCBgTkFgIHZhbHVlcywgYW5kIHRvIHNlZSB0aGUgbGFzdCBmZXcgY29sdW1ucyBvZiBhIHRpYmJsZQpbZ2dtYXBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZ21hcC9nZ21hcC5wZGYpIHwgdG8gZ2VvY29kZSB0aGUgZGF0YSAod2hpY2ggbWVhbnMgZ2V0IHRoZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIHZhbHVlcykKW3NmXShodHRwczovL3Itc3BhdGlhbC5naXRodWIuaW8vc2YvKSB8IHRvIG1vZGlmeSB0aGUgZ2VvY29kZWQgZGF0YSBzbyB0aGF0IG92ZXJsYXBwaW5nIHBvaW50cyBkaWQgbm90IG92ZXJsYXAKW2x1YnJpZGF0ZV0oaHR0cHM6Ly9sdWJyaWRhdGUudGlkeXZlcnNlLm9yZy8pIHwgdG8gd29yayB3aXRoIHRoZSBkYXRhLXRpbWUgZGF0YSAgICAKW0RUXShodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL0RULykgfCB0byBjcmVhdGUgdGhlIGludGVyYWN0aXZlIHRhYmxlICAKW2h0bWx0b29sc10oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL2h0bWx0b29scy92ZXJzaW9ucy8wLjUuMCkgfCB0byBhZGQgYSBjYXB0aW9uIHRvIG91ciBpbnRlcmFjdGl2ZSB0YWJsZSAKW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gY3JlYXRlIHBsb3RzICAKW2dnZm9yY2VdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZ2ZvcmNlL2dnZm9yY2UucGRmKSAgIHwgdG8gY3JlYXRlIGEgcGxvdCB6b29tCltmb3JjYXRzXShodHRwczovL2ZvcmNhdHMudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHJlb3JkZXIgZmFjdG9yIGZvciBwbG90Clt3YWZmbGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9ocmJybXN0ci93YWZmbGUpIHwgdG8gbWFrZSB3YWZmbGUgcHJvcG9ydGlvbiBwbG90cyAgCltwb2xpc2NpZGF0YV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BvbGlzY2lkYXRhL3BvbGlzY2lkYXRhLnBkZikgfCB0byBnZXQgcG9wdWxhdGlvbiB2YWx1ZXMgZm9yIHRoZSBzdGF0ZXMKW2ZsZXhkYXNoYm9hcmRdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2ZsZXhkYXNoYm9hcmQvKSAgICAgfCB0byBjcmVhdGUgdGhlIGRhc2hib2FyZCAgCltzaGlueV0oaHR0cHM6Ly9zaGlueS5yc3R1ZGlvLmNvbS8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGFsbG93IG91ciBkYXNoYm9hcmQgdG8gYmUgaW50ZXJhY3RpdmUgICAKW2xlYWZsZXRdKGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vbGVhZmxldC9zaGlueS5odG1sKSB8IHRvIGltcGxlbWVudCB0aGUgW2xlYWZsZXRdKGh0dHA6Ly9sZWFmbGV0anMuY29tLykgKGEgSmF2YVNjcmlwdCBsaWJyYXJ5IGZvciBtYXBzKSB0byBjcmVhdGUgdGhlIG1hcCBmb3Igb3VyIGRhc2hib2FyZCAgIAoKVGhlIGZpcnN0IHRpbWUgd2UgdXNlIGEgZnVuY3Rpb24sIHdlIHdpbGwgdXNlIHRoZSBgOjpgIHRvIGluZGljYXRlIHdoaWNoIHBhY2thZ2Ugd2UgYXJlIHVzaW5nLiBVbmxlc3Mgd2UgaGF2ZSBvdmVybGFwcGluZyBmdW5jdGlvbiBuYW1lcywgdGhpcyBpcyBub3QgbmVjZXNzYXJ5LCBidXQgd2Ugd2lsbCBpbmNsdWRlIGl0IGhlcmUgdG8gYmUgaW5mb3JtYXRpdmUgYWJvdXQgd2hlcmUgdGhlIGZ1bmN0aW9ucyB3ZSB3aWxsIHVzZSBjb21lIGZyb20uCgoKIyAqKkNvbnRleHQqKgoqKiogCioqV2hhdCBleGFjdGx5IGFyZSBvcGlvaWRzPyoqCgpBY2NvcmRpbmcgdG8gdGhlIFtERUFdKGh0dHBzOi8vd3d3LmRlYS5nb3YvdGF4b25vbXkvdGVybS8zMzEpIGFuZCB0aGUgW0FsdGEgTWlyYSBhZGRpY3Rpb24gdHJlYXRtZW50IGNlbnRlcl0oaHR0cHM6Ly93d3cuYWx0YW1pcmFyZWNvdmVyeS5jb20vb3BpYXRlcy9kaWZmZXJlbmNlLW9waWF0ZXMtb3Bpb2lkcy8pOgoKT3Bpb2lkcyAoYWxzbyBrbm93biBhcyBuYXJjb3RpY3Mgd2hpY2ggY29tZXMgZnJvbSB0aGUgR3JlZWsgd29yZCBmb3IgInN0dXBvciIpLCBkZXNjcmliZXMgYSBjbGFzcyBvZiBkcnVncyB0aGF0IGNvbnRhaW4gW29waXVtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9PcGl1bSkgKHRoZSBwb3BweSBwbGFudCAtIFsqUGFwYXZlciBzb21uaWZlcnVtKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGFwYXZlcl9zb21uaWZlcnVtKSksIGFyZSBkZXJpdmVkIGZyb20gb3BpdW0sIG9yIGNvbnRhaW4gYSBzZW1pLXN5bnRoZXRpYyBvciBzeW50aGV0aWMgc3Vic3RpdHV0ZSBmb3Igb3BpdW0uCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJpbmdvLWRvZXJyaWUtVGk2U2s1clpSUDgtdW5zcGxhc2guanBnIiApKQoKYGBgCgo8c3Bhbj5QaG90byBieSA8YSBocmVmPSJodHRwczovL3Vuc3BsYXNoLmNvbS9AaW5nb2RvZXJyaWU/dXRtX3NvdXJjZT11bnNwbGFzaCZhbXA7dXRtX21lZGl1bT1yZWZlcnJhbCZhbXA7dXRtX2NvbnRlbnQ9Y3JlZGl0Q29weVRleHQiPkluZ28gRG9lcnJpZTwvYT4gb24gPGEgaHJlZj0iaHR0cHM6Ly91bnNwbGFzaC5jb20vcy9waG90b3Mvb3BpdW0/dXRtX3NvdXJjZT11bnNwbGFzaCZhbXA7dXRtX21lZGl1bT1yZWZlcnJhbCZhbXA7dXRtX2NvbnRlbnQ9Y3JlZGl0Q29weVRleHQiPlVuc3BsYXNoPC9hPjwvc3Bhbj4KCgpIb2V3dmVyLCB0ZWNobmljYWxseSwgb3Bpb2lkcyBhcmUgc3Vic3RhbmNlcyB0aGF0IGJpbmQgdG8gdGhlIFtvcGlvaWQgcmVjZXB0b3JzXShodHRwczovL3d3dy5zY2llbmNlZGFpbHkuY29tL3JlbGVhc2VzLzIwMDcvMTAvMDcxMDE0MTYzNjQ3Lmh0bSM6fjp0ZXh0PVRoZSUyMG9waW9pZCUyMHN5c3RlbSUyMGNvbnNpc3RzJTIwb2YsYW5kJTIwcG90ZW50aWFsbHklMjBpbml0aWF0aW5nJTIwYWRkaWN0aXZlJTIwYmVoYXZpb3JzLikgaW4gdGhlIGJvZHksIHdoaWNoIGFyZSBpbnZvbHZlZCBpbiB0aGUgc2Vuc2F0aW9uIG9mIGBwYWluYCBhbmQgdGhlIGV4cGVyaWVuY2Ugb2YgW3Jld2FyZF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUmV3YXJkX3N5c3RlbSM6fjp0ZXh0PVRoZSUyMHJld2FyZCUyMHN5c3RlbSUyMGlzJTIwYSxpbnZvbHZlJTIwcGxlYXN1cmUlMjBhcyUyMGElMjBjb3JlKS4gVGhlcmUgYXJlIGFjdHVhbGx5IG9waW9pZHMgdGhhdCBuYXR1cmFsbHkgYXJlIG1hZGUgYnkgdGhlIGh1bWFuIGJvZHksIHRoZSBtb3N0IHdlbGwga25vd24gYmVpbmcgdGhlIFtlbmRvcnBoaW5zXShodHRwczovL3d3dy5tZWRpY2FsbmV3c3RvZGF5LmNvbS9hcnRpY2xlcy8zMjA4MzkjOn46dGV4dD1FbmRvcnBoaW5zJTIwYXJlJTIwY2hlbWljYWxzJTIwcHJvZHVjZWQlMjBieSxzdXJnZXJ5JTIwb3IlMjBmb3IlMjBwYWluJTJEcmVsaWVmLikuCgoKT3Bwb2lkIGRydWdzIHRlbmQgdG8gYmUgYWRkaWN0aXZlIGJlY3Vhc2UgdGhleSBtb2R1bGF0ZSB0aGUgW3Jld2FyZCBzeXN0ZW1dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1Jld2FyZF9zeXN0ZW0jOn46dGV4dD1UaGUlMjByZXdhcmQlMjBzeXN0ZW0lMjBpcyUyMGEsaW52b2x2ZSUyMHBsZWFzdXJlJTIwYXMlMjBhJTIwY29yZSkuIFRoaXMgaXMgdGhlIHBhcnQgb2YgdGhlIGJyYWluIHRoYXQgcmVpbmZvcmNlcyBiZWhhdmlvcnMgKG5vcm1hbGx5IHRoZXNlIGFyZSBiZWhhdmlvdXJzIHN1Y2ggYXMgZHJpbmtpbmcgd2F0ZXIgb3IgZWF0aW5nIGZvb2QpIGJ5IGNhdXNpbmcgdGhlIGV4cGVyaWVuY2Ugb2YgcGxlYXN1cmUgKHRocm91Z2ggdGhlIHJlbGVhc2Ugb2YgYSBuZXVyb3RyYW5zbWl0dGVyIGNhbGxlZCBbZG9wYW1pbmVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RvcGFtaW5lKSkuIAoKVGhpcyBzYW1lIHN5c3RlbSBjYW4gYmUgYWN0aXZhdGVkIGJ5IGJvdGggb3Bpb2lkcyB0aGF0IG5hdHVyYWxseSBvY2N1ciBpbiB0aGUgYm9keSwgYXMgd2VsbCBhcyBvcGlvaWQgcGVyc2NyaXB0aW9uIGRydWdzIGFuZCBvdGhlciBhZGRpY3RpdmUgZHJ1Z3MuIEFjdGl2YXRpb24gb2YgdGhpcyBzeXRlbSBieSBkcnVnIHVzZSAgbGVhZHMgdG8gdmVyeSBoaWdoIHJlbGVhc2VzIG9mIERvcGFtaW5lIGFuZCB0aGUgc2Vuc2F0aW9uIG9mIHBsZWFzdXJlIHdoaWNoIHVsdGltYXRlbHkgbGVhZHMgdG8gcmVpbmZvcmNlZCB1c2Ugb2YgdGhhdCBkcnVnLgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vd3d3LmRydWdhYnVzZS5nb3Yvc2l0ZXMvZGVmYXVsdC9maWxlcy9zdHlsZXMvY29udGVudF9pbWFnZV9sYXJnZS9wdWJsaWMvZHJ1Z3N0YXJnZXR0aGVicmFpbnNwbGVhc3VyZWNlbnRlci5naWY/aXRvaz1GZmRfUENlYiIpCmBgYAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmRydWdhYnVzZS5nb3YvcHVibGljYXRpb25zL2RydWdzLWJyYWlucy1iZWhhdmlvci1zY2llbmNlLWFkZGljdGlvbi9kcnVncy1icmFpbikKCgpJbiBnZW5lcmFsLCBvcGlvaWRzIG1lZGljYXRpb25zIGFuZCBkcnVncyBoYXZlIGJlZW4gZm91bmQgdG8gZHVsbCB0aGUgc2Vuc2VzLCByZWxlaXZlIHBhaW4sIHN1cHJlc3MgY291Z2gsIHJlZHVjZSByZXNwaXJhdGlvbiBhbmQgaGVhcnQgcmF0ZSwgaW5kdWNlIGNvbnN0aXBhdGlvbiwgYW5kIGluZHVjZSBmZWVsaW5ncyBvZiBldXBob3JpYS4gVGhleSBoYXZlIGEgaGlnaCBwb3RlbnRpYWwgZm9yIGFidXNlIGFuZCBhZGRpY3Rpb24uCgpEcnVncyB3aXRoaW4gdGhpcyBjbGFzcyBpbmNsdWRlICh3aXRoIHBlcnNjcmlwdGlvbiBkcnVnIGJyYW5kIG5hbWVzIGFyZSBzaG93biBpbiBwYXJlbnRoZXNlcyk6IAoKMSkgTm9uLXN5bnRoZXRpYyBwdXJpZmllZDogTW9yaHBpbmUsIENvZGVpbmUsIFRoZWJhaW5lCjIpIFNlbWktc3ludGhldGljOiAgSGVyb2luLCBPeHljb2RvbmUgKE94eUNvbnRpbiwgT3hlY3RhLCBSb3hpY29kb25lKSwgYW5kIEh5ZHJvY29kb25lICggVmljb2RpbiwgTG9ydGFiLCBMb3JjZXQpKSwgb3h5bW9ycGhvbmUgKE9wYW5hKSwgSHlkcm9tb3JwaG9uZSAoRGlsYXVkaWQsIEV4YWxnbykKMykgU3ludGhldGljOiBNZXBlcmlkaW5lIChEZW1lcm9sKSwgTWV0aGFkb25lIChNZXRoYWRvc2UsIERvbG9waGluZSksIGFuZCBGZW50YW55bCAoQWJzdHJhbCwgQWN0aXEsIEZlbnRvcmEsIER1cmFnZXNpYywgTGF6YW5kYSwgU3Vic3lzKSwgVHJhbWFkb2wgKENvblppcCwgUnl6b2x0LCBVbHRyYW0pCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI0MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJPcGl1bV9wb2RfY3V0X3RvX2RlbW9uc3RyYXRlX2ZsdWlkX2V4dHJhY3Rpb24xLmpwZyIgKSkKCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GaWxlOk9waXVtX3BvZF9jdXRfdG9fZGVtb25zdHJhdGVfZmx1aWRfZXh0cmFjdGlvbjEuanBnKQoKT3BpdW0gY29tZXMgZnJvbSB0aGUgZmx1aWQgKHdoaWNoIGlzIGFsc28gY2FsbGVkIHBvcHB5IHRlYXJzKSBpbnNpZGUgdGhlIHNlZWQgY2FwdXN1bGVzIG9mIHRoZSBbKlBhcGF2ZXIgc29tbmlmZXJ1bSpdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BhcGF2ZXJfc29tbmlmZXJ1bSkgcGxhbnQuIFRoaXMgY29udGFpbnMgbW9ycGhpbmUsIGNvZGVpbmUsIGFuZCB0aGViYWluZS4gVGhpcyBpcyB0aGVuIGRyaWVkLiAKCk9waXVtIGhhcyBiZWVuIHVzZWQgYnkgaHVtYW5zIHNpbmNlIDUwMDAgQkNFIGFuZCBpdCBoYXMgYmVlbiB1c2VkIGFjcm9zcyB0aGUgd29ybGQuIFNlZSBbaGVyZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvT3BpdW0pIGZvciBhbiBpbnRlcmVzdGluZyBvdmVydmlldyBvZiB0aGUgaGlzdG9yeS4gCgoKT3BpdW0gZGVyaXZlZCBtZWRpY2F0aW9ucyB3ZXJlIGhpc3RvcmljYWxseSB1c2VkIGluIFVuaXRlZCBTdGF0ZXMgdG8gdHJlYXQgYSB2YXJpZXR5IG9mIGFpbG1lbnRzIGJlc2lkZXMgcGFpbiBpbmNsdWRpbmc6IGNob2xlcmEsIGR5c2VudGVyeSwgdHVidWVyY3Vsb3NpLCBhbmQgbWVudGFsIGlsbG5lc3MuICAKCk9mIG5vdGUsIHRoZXkgc3RhdGUgdGhhdCAiZnJvbSAxODk4IHRvIDE5MTAgaGVyb2luIHdhcyBtYXJrZXRlZCBhcyBhIG5vbi1hZGRpY3RpdmUgbW9ycGhpbmUgc3Vic3RpdHV0ZSBhbmQgY291Z2ggbWVkaWNpbmUgZm9yIGNoaWxkcmVuIiEKCkhlcmUgeW91IGNhbiBzZWUgYSBwaG90byBvZiBhIGJvdHRsZSBvZiBoZXJpb246CgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI0MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy90aHVtYi9mL2ZmL0JheWVyX0hlcm9pbl9ib3R0bGUuanBnLzIyMHB4LUJheWVyX0hlcm9pbl9ib3R0bGUuanBnIikKYGBgCgojIyMjIFtbc291cmNlXV0oaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy90aHVtYi9mL2ZmL0JheWVyX0hlcm9pbl9ib3R0bGUuanBnLzIyMHB4LUJheWVyX0hlcm9pbl9ib3R0bGUuanBnKQoKT3Bpb2lkcyBoYXZlIGNvbnRpbnVlZCB0byBiZSB1c2VkIGluIHRoZSB0cmVhdG1lbnQgb2YgcGFpbi4gCgojIyBUaGUgT3Bpb2lkIEVwaWRlbWljIAoKVGhlIG9waW9pZCBlcGlkZW1pYyBiZWdhbiBpbiB0aGUgbGF0ZSAxOTkwcy4gCgpBY2NvcmRpbmcgdG8gdGhlIFtVUyBkZXBhcnRtZW50IG9mIGhlYWx0aCBhbmQgaHVtYW4gc2VydmljZXMgKEhIUyldKApodHRwczovL3d3dy5oaHMuZ292L29waW9pZHMvYWJvdXQtdGhlLWVwaWRlbWljL2luZGV4Lmh0bWwpOgoKPiBJbiB0aGUgbGF0ZSAxOTkwcywgcGhhcm1hY2V1dGljYWwgY29tcGFuaWVzIHJlYXNzdXJlZCB0aGUgbWVkaWNhbCBjb21tdW5pdHkgdGhhdCBwYXRpZW50cyB3b3VsZCBub3QgYmVjb21lIGFkZGljdGVkIHRvIG9waW9pZCBwYWluIHJlbGlldmVycyBhbmQgaGVhbHRoY2FyZSBwcm92aWRlcnMgYmVnYW4gdG8gcHJlc2NyaWJlIHRoZW0gYXQgZ3JlYXRlciByYXRlcy4KCj4gSW5jcmVhc2VkIHByZXNjcmlwdGlvbiBvZiBvcGlvaWQgbWVkaWNhdGlvbnMgbGVkIHRvICoqd2lkZXNwcmVhZCBtaXN1c2UqKiBvZiBib3RoIHByZXNjcmlwdGlvbiBhbmQgbm9uLXByZXNjcmlwdGlvbiBvcGlvaWRzIGJlZm9yZSBpdCBiZWNhbWUgY2xlYXIgdGhhdCB0aGVzZSBtZWRpY2F0aW9ucyBjb3VsZCBpbmRlZWQgYmUgaGlnaGx5IGFkZGljdGl2ZS4KCj4gSW4gMjAxNyB0aGUgW0hIU10oaHR0cHM6Ly93d3cuaGhzLmdvdikgZGVjbGFyZWQgYSBwdWJsaWMgaGVhbHRoIGVtZXJnZW5jeSAKClNlZSBbaGVyZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVGltZWxpbmVfb2ZfdGhlX29waW9pZF9lcGlkZW1pYykgZm9yIGEgdGltZWxpbmUgb2YgdGhlIGVwaWRlbWljIGluIHRoZSBVUyBhbmQgW2hlcmVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL09waW9pZF9lcGlkZW1pY19pbl90aGVfVW5pdGVkX1N0YXRlcykgZm9yIG1vcmUgZGV0aWFscyBhYm91dCB0aGUgZXBpZGVtaWMuCgoKQWNjb3JkaW5nIHRvIHRoaXMgW2FydGljbGVdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbW13ci92b2x1bWVzLzY4L3dyL21tNjgwMmExLmh0bT9zX2NpZD1tbTY4MDJhMV93KSBmcm9tIHRoZSBbTW9yYmlkaXR5IGFuZCBNb3J0YWxpdHkgV2Vla2x5IFJlcG9ydCAoTU1XUildKGh0dHBzOi8vd3d3LmNkYy5nb3YvbW13ci9hYm91dC5odG1sKSBvZiB0aGUgW0NlbnRlcnMgZm9yIERpc2Vhc2UgQ29udHJvbCBhbmQgUHJldmVudGlvbiAoQ0RDKV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ2VudGVyc19mb3JfRGlzZWFzZV9Db250cm9sX2FuZF9QcmV2ZW50aW9uKToKCj4gRHJ1ZyBvdmVyZG9zZSBpcyB0aGUgKipsZWFkaW5nIGNhdXNlKiogb2YgdW5pbnRlbnRpb25hbCBpbmp1cnktYXNzb2NpYXRlZCBkZWF0aCBpbiB0aGUgVW5pdGVkIFN0YXRlcy4KCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJPcGlvaWRzX0luZm9ncmFwaGljLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuaGhzLmdvdi9vcGlvaWRzL3NpdGVzL2RlZmF1bHQvZmlsZXMvMjAxOS0xMS9PcGlvaWRzJTIwSW5mb2dyYXBoaWNfbGV0dGVyU2l6ZVBERl8xMC0wMi0xOS5wZGYpCgoKQWNjb3JkaW5nIHRvIHRoZSBbQ0RDXShodHRwczovL3d3dy5jZGMuZ292L2RydWdvdmVyZG9zZS9lcGlkZW1pYy9pbmRleC5odG1sKSwgdGhlcmUgd2VyZSAzIHdhdmVzIG9mIHRoZSBlcGlkZW1pYzoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICIyMDE4LTMtV2F2ZS1MaW5lcy1Nb3J0YWxpdHkucG5nIikpCgpgYGAKCiMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5jZGMuZ292L2RydWdvdmVyZG9zZS9pbWFnZXMvZXBpZGVtaWMvMjAxOC0zLVdhdmUtTGluZXMtTW9ydGFsaXR5LnBuZykKCllvdSBjYW4gc2VlIHRoYXQgbW90aCByZWNlbnQgb3ZlcmRvc2UgZGVhdGhzIHdlcmUgZHVlIHRvIHRoZSB1c2Ugb2Ygc3ludGhldGljIG9waW9pZHMsIHdoZXJlIGFzIHByZXZpb3VzIGhpZ2ggbGV2ZWxzIG9mIG92ZXJkb3NlcyAodGlsbCBhYm91dCAyMDE1KSB3ZXJlIGF0dHJpYnV0YWJsZSB0byBuYXR1cmFsIGFuZCBzZW1pLXN5bnRoZXRpYyBvcGlvaWRzICh3aGljaCBpcyB3aGF0IHdlIHdpbGwgbG9vayBhdCBpbiB0aGlzIGNhc2Ugc3R1ZHkpLiAKClRoZXkgc3RhdGUgdGhhdDogCgo+IEZyb20gMTk5OeKAkzIwMTgsIGFsbW9zdCAqKjQ1MCwwMDAqKiBwZW9wbGUgZGllZCBmcm9tIGFuICoqb3ZlcmRvc2UgaW52b2x2aW5nIGFueSBvcGlvaWQqKiwgaW5jbHVkaW5nIHByZXNjcmlwdGlvbiBhbmQgaWxsaWNpdCBvcGlvaWRzLgoKCkltcG9ydGFudGx5IHJhdGVzIGFwcGVhciB0byBkaWZmZXIgYWNyb3NzIHN0YXRlcywgYWNjb3JkaW5nIHRvIHRoaXMgW0NEQyByZXBvcnRdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbW13ci92b2x1bWVzLzY3L3dyL21tNjc1MTUyZTEuaHRtP3NfY2lkPW1tNjc1MTUyZTFfdykgCgoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3d3dy5jZGMuZ292L21td3Ivdm9sdW1lcy82Ny93ci9maWd1cmVzL21tNjc1MTUyZTEtRi5naWYiKQoKYGBgCgpbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbW13ci92b2x1bWVzLzY3L3dyL2ZpZ3VyZXMvbW02NzUxNTJlMS1GLmdpZikKCgpBY2NvcmRpbmcgdG8gdGhlIFttb3RpdmF0aW5nIHJlcG9ydF0oaHR0cHM6Ly93d3cuY2RjLmdvdi9tbXdyL3ZvbHVtZXMvNjgvd3IvcGRmcy9tbTY4MDJhMS1ILnBkZikgZm9yIG91ciBjYXNlIHN0dWR5OiAKClBlcnNjcmlwdGlvbiByYXRlcyBhcmUgbm93IGRlY2xpbmluZywgaG93ZXZlciwgcGVyc2NyaXB0aW9uIG9mIG9waW9pZHMgd2FzIGZvdW5kIHRvIGJlIGhpZ2hlciBpbiBydXJhbCBhcmVhcyByYXRoZXIgdGhhbiB1cmJhbiBhcmVzLiAKCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiY29udGV4dC5wbmciKSkKCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5jZGMuZ292L21td3Ivdm9sdW1lcy82OC93ci9wZGZzL21tNjgwMmExLUgucGRmKQogCkl0IGlzIGltcG9ydGFudCB0byBpZGVudGlmeSBsb2NhdGlvbnMgd2hlcmUgcGVvcGxlIGFyZSBwYXJ0aWN1bGFybHkgdnVsZXJuYWJsZSB0byB0YXJnZXQgaW50ZXJ2ZW50aW9ucyBmb3IgY29tbXVuaXRpZXMgdGhhdCBuZWVkIGl0IHRoZSBtb3N0LgoKIAojICoqTGltaXRhdGlvbnMqKgoqKiogClRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBjb25zaWRlcmF0aW9ucyByZWdhcmRpbmcgdGhpcyBkYXRhIGFuYWx5c2lzIHRvIGtlZXAgaW4gbWluZDogCgpBY2NvcmRpbmcgdG8gdGhlIFtXYXNoaW5ndG9uIFBvc3QgZGF0YV0oaHR0cHM6Ly93d3cud2FzaGluZ3RvbnBvc3QuY29tL25hdGlvbmFsLzIwMTkvMDcvMTgvaG93LWRvd25sb2FkLXVzZS1kZWEtcGFpbi1waWxscy1kYXRhYmFzZS8gYWJvdXQgdGhlIERFQSBkYXRhOgoKPiJJdOKAmXMgaW1wb3J0YW50IHRvIHJlbWVtYmVyIHRoYXQgdGhlIG51bWJlciBvZiBwaWxscyBpbiBlYWNoIGNvdW50eSBkb2VzIG5vdCBuZWNlc3NhcmlseSBtZWFuIHRob3NlIHBpbGxzIHdlbnQgdG8gcGVvcGxlIHdobyBsaXZlIGluIHRoYXQgY291bnR5LiBUaGUgZGF0YSBvbmx5IHNob3dzIHVzIHdoYXQgcGhhcm1hY2llcyB0aGUgcGlsbHMgYXJlIHNoaXBwZWQgdG8gYW5kIG5vdGhpbmcgZWxzZS4iCgpGdXJ0aGVybW9yZSwgd2Ugd2lsbCBkZWZpbmUgY291bnRpZXMgYXMgYmVpbmcgcnVyYWwgb3IgdXJiYW4gaG93ZXZlciB0aGVyZSBjYW4gYmUgZ3JlYXQgdmFyaWF0aW9uIHdpdGhpbiBhIGNvdW50eSBhbmQgd2UgdXNlZCBsYW5kIGFyZWEgdmFsdWVzIGZvcm0gb25seSAyMDEwIGV2ZW4gdGhvdWdoIHRoZXNlIGNhbiBmbHVjdHVhdGUuIFRoZXJlZm9yZSB0aGUgd2F5IHdlIGNhdGVnb3JpemVkIGNvdW50aWVzIHNob3VsZCBiZSBzZWVuIGFzIGFuIGFwcHJveGltYXRpb24uCgpGaW5hbGx5LCBvdmVyZG9zZSBkZWF0aHMgYXJlIG9mdGVuIGR1ZSB0byB0aGUgdXNlIG9mIG11bHRpcGxlIHN1YnN0YW5jZXMuIFNpbXBseSBiZWNhdXNlIGEgY291bnR5IHJlY2lldmVkIG1vcmUgcGlsbHMgZG9lcyBub3QgIG1lYW4gdGhhdCBwZW9wbGUgaW4gdGhhdCBjb3VudHkgd291bGQgZXhwZXJpZW5jZSBtb3JlIGRydWcgb3ZlcmRvc2VzLiBJdCBpcyBhbHNvIGltcG9ydGFudCB0byByZW1lbWJlciB0aGF0IHBlcnNjcmlwdGlvbiBvcGlvaWRzIG9ubHkgYWNjb3VudCBmb3IgYSBwb3J0aW9uIG9mIHRoZSBkcnVnIG92ZXJkb3NlIGRlYXRocyByZXBvcnRlZCBpbiB0aGlzIHRpbWUgcGVyaW9kLiBIb3dldmVyLCBhY2NvcmRpbmcgdG8gdGhpcyBbYXJ0aWNsZV0oaHR0cHM6Ly9qYW1hbmV0d29yay5jb20vam91cm5hbHMvamFtYXBzeWNoaWF0cnkvZnVsbGFydGljbGUvMTg3NDU3NSkgNzUlIG9mIGhlcm9pbiB1c2VycyBzdXJ2ZXllZCB3ZXJlIGludHJvZHVjZWQgdG8gb3Bpb2lkcyB0aHJvdWdoIHBlcnNjcmlwdGlvbiBkcnVnIHVzZS4KCgojICoqV2hhdCBhcmUgdGhlIGRhdGE/KioKKioqIAoKV2Ugd2lsbCB1c2UgZGF0YSBmcm9tIHR3byBzb3VyY2VzOgoKMSkgVGhlIFVTIGNlbnN1cyBmb3IgbGFuZCBhcmVhIG9mIGNvdW50aWVzIHRvIGFsbG93IHVzIHRvIGV4dGltYXRlIGNvdW50eS1sZXZlbCBwb3B1bGF0aW9uIGRlbnNpdHkgIAoKMikgVGhlIFtXYXNoaW5ndG9uIFBvc3QgZGF0YV0oaHR0cHM6Ly93d3cud2FzaGluZ3RvbnBvc3QuY29tL25hdGlvbmFsLzIwMTkvMDcvMTgvaG93LWRvd25sb2FkLXVzZS1kZWEtcGFpbi1waWxscy1kYXRhYmFzZS8pZnJvbSB0aGUgW0RydWcgRW5mb3JjZW1lbnQgQWRtaW5pc3RyYXRpb24gKERFQSldKGh0dHBzOi8vd3d3LmRlYS5nb3YvKSBhYm91dCBvcGlvaWQgKFtveHljb2RvbmVdKGh0dHBzOi8vd3d3LmRlYS5nb3Yvc2l0ZXMvZGVmYXVsdC9maWxlcy8yMDIwLTA2L094eWNvZG9uZS0yMDIwXzAucGRmKSBhbmQgW2h5ZHJvY29kb25lXShodHRwczovL3d3dy5kZWFkaXZlcnNpb24udXNkb2ouZ292L2RydWdfY2hlbV9pbmZvL2h5ZHJvY29kb25lLnBkZikpIHBpbGwgc2hpcG1lbnRzIHRvIHBoYXJtYWNpZXMgYW5kIHBhcmFjdGl0aW9uYWVycyBhcm91bmQgdGhlIFVTIGF0IHRoZSBjb3VudHktbGV2ZWwKClRoaXMgZGF0YXNldCB3YXMgcmVsZWFzZWQgaW4gSnVseSBvZiAyMDE5IGFuZCBoYXMgYmVlbiBjb250cm92ZXJzaWFsIGFzIGFjY29yZGluZyB0byB0aGUgV2FzaGluZ3RvbiBQb3N0OgoKPiBUaGUgZGlzY2xvc3VyZSBpcyBwYXJ0IG9mIGEgY2l2aWwgYWN0aW9uIGJyb3VnaHQgYnkgMiw1MDAgY2l0aWVzLCB0b3ducywgY291bnRpZXMgYW5kIHRyaWJhbCBuYXRpb25zIGFsbGVnaW5nIHRoYXQgbmVhcmx5IHR3byBkb3plbiBkcnVnIGNvbXBhbmllcyAqKmNvbnNwaXJlZCB0byBzYXR1cmF0ZSB0aGUgbmF0aW9uIHdpdGggb3Bpb2lkcyoqLgoKU2VlIFtoZXJlXShodHRwczovL3d3dy53YXNoaW5ndG9ucG9zdC5jb20vbmF0aW9uYWwvMjAxOS8wNy8yMC9vcGlvaWQtZmlsZXMvP2FyYzQwND10cnVlKSBmb3IgbW9yZSBkZXRhaWxzIGFib3V0IGhvdyB0aGlzIGRhdGFiYXNlIHdhcyByZWxlYXNlZC4KClRoZSBbV2FzaGluZ3RvbiBQb3N0XShodHRwczovL3d3dy53YXNoaW5ndG9ucG9zdC5jb20vbmF0aW9uYWwvMjAxOS8wNy8xOC9ob3ctZG93bmxvYWQtdXNlLWRlYS1wYWluLXBpbGxzLWRhdGFiYXNlLylzdGF0ZXMgdGhhdCB0aGV5OgoKPi4uIGNsZWFuZWQgdGhlIGRhdGEgdG8gaW5jbHVkZSBvbmx5IGluZm9ybWF0aW9uIG9uIHNoaXBtZW50cyBvZiBveHljb2RvbmUgYW5kIGh5ZHJvY29kb25lIHBpbGxzLiBXZSBkaWQgbm90IGluY2x1ZGUgZGF0YSBvbiAxMCBvdGhlciBvcGlvaWRzIGJlY2F1c2UgdGhleSB3ZXJlIHNoaXBwZWQgaW4gbXVjaCBsb3dlciBxdWFudGl0aWVzLi4uCgo+SXTigJlzIGltcG9ydGFudCB0byByZW1lbWJlciB0aGF0IHRoZSBudW1iZXIgb2YgcGlsbHMgaW4gZWFjaCBjb3VudHkgZG9lcyBub3QgbmVjZXNzYXJpbHkgbWVhbiB0aG9zZSBwaWxscyB3ZW50IHRvIHBlb3BsZSB3aG8gbGl2ZSBpbiB0aGF0IGNvdW50eS4gVGhlIGRhdGEgb25seSBzaG93cyB1cyB3aGF0IHBoYXJtYWNpZXMgdGhlIHBpbGxzIGFyZSBzaGlwcGVkIHRvIGFuZCBub3RoaW5nIGVsc2UuCgpUaGlzIGRhdGEgd2FzIHBhcnQgb2YgdGhlIFtBdXRvbWF0ZWQgUmVwb3J0cyBhbmQgQ29uc29saWRhdGVkIE9yZGVyaW5nIFN5c3RlbSAoQVJDT1MpXWh0dHBzOi8vd3d3LmRlYWRpdmVyc2lvbi51c2Rvai5nb3YvYXJjb3MvcmV0YWlsX2RydWdfc3VtbWFyeS8gb2YgdGhlIERFQSBpbiB3aGljaDoKCj4gbWFudWZhY3R1cmVycyBhbmQgZGlzdHJpYnV0b3JzIHJlcG9ydCB0aGVpciBjb250cm9sbGVkIHN1YnN0YW5jZXMgdHJhbnNhY3Rpb25zCgpUaGVpciBbd2Vic2l0ZV0oaHR0cHM6Ly93d3cuZGVhZGl2ZXJzaW9uLnVzZG9qLmdvdi9hcmNvcy9pbmRleC5odG1sI2JhY2tncm91bmQpIGluZGljYXRlcyB0aGF0OiAKCgo+IFRoZSBDb250cm9sbGVkIFN1YnN0YW5jZXMgQWN0IG9mIDE5NzAgIGNyZWF0ZWQgdGhlIHJlcXVpcmVtZW50IGZvciBNYW51ZmFjdHVyZXJzIGFuZCBEaXN0cmlidXRvcnMgdG8gcmVwb3J0IHRoZWlyIGNvbnRyb2xsZWQgc3Vic3RhbmNlcyB0cmFuc2FjdGlvbnMgdG8gdGhlIEF0dG9ybmV5IEdlbmVyYWwuIFRoZSBBdHRvcm5leSBHZW5lcmFsIGRlbGVnYXRlcyB0aGlzIGF1dGhvcml0eSB0byB0aGUgRHJ1ZyBFbmZvcmNlbWVudCBBZG1pbmlzdHJhdGlvbiAoREVBKS4KCj4gQVJDT1MgaXMgYW4gYXV0b21hdGVkLCBjb21wcmVoZW5zaXZlIGRydWcgcmVwb3J0aW5nIHN5c3RlbSB3aGljaCBtb25pdG9ycyB0aGUgZmxvdyBvZiBERUEgY29udHJvbGxlZCBzdWJzdGFuY2VzIGZyb20gdGhlaXIgcG9pbnQgb2YgbWFudWZhY3R1cmUgdGhyb3VnaCBjb21tZXJjaWFsIGRpc3RyaWJ1dGlvbiBjaGFubmVscyB0byBwb2ludCBvZiBzYWxlIG9yIGRpc3RyaWJ1dGlvbiBhdCB0aGUgZGlzcGVuc2luZy9yZXRhaWwgbGV2ZWwgLSBob3NwaXRhbHMsIHJldGFpbCBwaGFybWFjaWVzLCBwcmFjdGl0aW9uZXJzLCBtaWQtbGV2ZWwgcHJhY3RpdGlvbmVycywgYW5kIHRlYWNoaW5nIGluc3RpdHV0aW9ucy4gSW5jbHVkZWQgaW4gdGhlIGxpc3Qgb2YgY29udHJvbGxlZCBzdWJzdGFuY2UgdHJhbnNhY3Rpb25zIHRyYWNrZWQgYnkgQVJDT1MgYXJlIHRoZSBmb2xsb3dpbmc6IEFsbCBTY2hlZHVsZXMgSSBhbmQgSUkgbWF0ZXJpYWxzIChtYW51ZmFjdHVyZXJzIGFuZCBkaXN0cmlidXRvcnMpOyBTY2hlZHVsZSBJSUkgbmFyY290aWMgYW5kIGdhbW1hLWh5ZHJveHlidXR5cmljIGFjaWQgKEdIQikgbWF0ZXJpYWxzIChtYW51ZmFjdHVyZXJzIGFuZCBkaXN0cmlidXRvcnMpOyBhbmQgc2VsZWN0ZWQgU2NoZWR1bGUgSUlJIGFuZCBJViBwc3ljaG90cm9waWMgZHJ1Z3MgKG1hbnVmYWN0dXJlcnMgb25seSkuCgpUaGUgYW5udWFsIHJlcG9ydCBhYm91dCB0aGUgZGF0YSBmcm9tIDIwMTksIGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly93d3cuZGVhZGl2ZXJzaW9uLnVzZG9qLmdvdi9hcmNvcy9yZXRhaWxfZHJ1Z19zdW1tYXJ5L3JlcG9ydF95cl8yMDE5LnBkZikuCgpBcyB0aGlzIGlzIGEgdmVyeSBsYXJnZSBkYXRhc2V0LCB0aHVzIHRoZSBXYXNoaW5ndG9uIFBvc3QgY3JlYXRlZCBhbiBbYXBwbGljYXRpb24gcHJnb3JhbW1pbmcgaW50ZXJmYWNlIChBUEkpXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9BUEkpICB0byBtYWtlIGl0IGVhc2llciBmb3IgdXNlcnMgdG8gYWNjZXNzIHRoZSBkYXRhLiAKCkFuIEFQSSBpcyBhIGNvbXB1dGF0aW9uYWwgaW50ZXJmYWNlIHRoYXQgc2ltcGxpZmllcyBpbnRlcmFjdGFjdHMgd2l0aCBhIGRhdGEgb3IgZmlsZSBzeXN0ZW0gZm9yIGEgdXNlci4gSXQgaXMgc2ltaWxhciB0byBhIFtHcmFwaGljYWwgVXNlciBJbnRlcmZhY2UgR1VJXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HcmFwaGljYWxfdXNlcl9pbnRlcmZhY2UpLCB5ZXQgaXQgYWxsb3dzIHRoZSB1c2VyIHNvbWUgbW9yZSBmbGV4aWJpbGl0eS9mdW5jdGlvbmFsaXR5LgoKVGhpcyBbbGlua10oaHR0cHM6Ly9hcmNvcy1hcGkuZXh0Lm5pbGUud29ya3MvX19zd2FnZ2VyX18vKSB0YWtlcyB5b3UgdG8gdGhlIFdhc2hpbmd0b24gUG9zdCBBUkNPUyBBUEkuIAoKVGhlcmUgd2FzIGFsc28gYW4gUiBwYWNrYWdlIG9uIGNyYW4gY2FsbGVkIFthcmNvc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvcGFja2FnZT1hcmNvcykgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIEFQSSwgYnV0IHRoaXMgaGFzIGJlZW4gYXJjaGl2ZWQuICBUaGlzIHBhY2thZ2UgaXMgaG93ZXZlciBzdGlsbCBhdmFpbGFibGUgW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS93cGludmVzdGlnYXRpdmUvYXJjb3MpIG9uIEdpdGh1Yi4KClNlZSBbaGVyZV0oaHR0cHM6Ly93d3cud2FzaGluZ3RvbnBvc3QuY29tL25hdGlvbmFsLzIwMTkvMDcvMTgvaG93LWRvd25sb2FkLXVzZS1kZWEtcGFpbi1waWxscy1kYXRhYmFzZS8pIGZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IGhvdyB0byBnZXQgYWNjZXNzIHRoZSBXYXNoaW5ndG9uIFBvc3QgREVBIGRhdGFiYXNlLgoKCiMgKipEYXRhIEltcG9ydCoqCioqKiAKCiMjIExhbmQgQXJlYQoKV2Ugd2lsbCBuZWVkIGxhbmQgYXJlYSBkYXRhIGZvciBvdXIgY2FsY3VsYXRpb25zIG9mIHBvcHVsYXRpb24gZGVuc2l0eS4gCgpXZSBvYnRhaW5lZCBjb3VudHkgbGFuZCBhcmVhIGRhdGEgZnJvbSB0aGUgVVMgY2Vuc3VzIEJ1cmVhdSBhdCB0aGlzIFtsaW5rXShodHRwczovL3d3dy5jZW5zdXMuZ292L2xpYnJhcnkvcHVibGljYXRpb25zLzIwMTEvY29tcGVuZGlhL3VzYS1jb3VudGllcy0yMDExLmh0bWwjTE5EKQoKVGhpcyBbbGlua10oaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9saWJyYXJ5L3B1YmxpY2F0aW9ucy8yMDExL2NvbXBlbmRpYS91c2EtY291bnRpZXMtMjAxMS9maWxlLWxheW91dC5odG1sKSBleHBsYWlucyBob3cgdGhlIGRhdGEgaXMgZm9ybWF0ZWQuCgpXZSB3aWxsIHVzZSB0aGUgYHJlYWRfZXhjZWwoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWFkeGxgIHBhY2thZ2UgdG8gaW1wb3J0IHRoZSBkYXRhLiBXZSB3aWxsIGFsc28gY29udmVydCB0aGUgZGF0YSBpbnRvIGEgW3RpYmJsZV0oaHR0cHM6Ly90aWJibGUudGlkeXZlcnNlLm9yZy8pICh3aGljaCBpcyBhIHRoZSB0aWR5dmVyc2UgdmVyc2lvbiBvZiBhIGRhdGEgZnJhbWUpIGJ5IHVzaW5nIHRoZSBgYXNfdGliYmxlKClgIGZ1bmN0aW9uIG9mIHRoZSBgdGliYmxlYCBwYWNrYWdlLgoKYGBge3J9CmxhbmQgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKGhlcmU6OmhlcmUoImRhdGEiLCAiTE5EMDEueGxzIikpCmxhbmQgPC0gYXNfdGliYmxlKGxhbmQpCmBgYAoKV2UgY2FuIHRha2UgYSBsb29rIGF0IHRoZSBkYXRhIHVzaW5nIHRoZSBiYXNlIGBoZWFkKClgIGZ1bmN0aW9uIHdoaWNoIHdpbGwgc2hvdyB0aGUgZnJpc3QgNiByb3dzLgoKYGBge3J9CmhlYWQobGFuZCkKYGBgCgpMb29rcyBnb29kIQoKIyMgQWNjZXNzaW5nIEFQSXMKClRoZSBgaHR0cmAgcGFja2FnZSBmb3JtYXRzIHdoYXQgYXJlIGNhbGxlZCAiR0VUIHJlcXVlc3RzIiBzbyB0aGF0IHRoZXkgd2lsbCB3b3JrIHByb3Blcmx5LiBUaGlzIGFsbG93cyBmb3IgdGhlIGRhdGEgdG8gYmUgcmV0cmlldmVkIGZyb20gdGhlIEFQSS4KClRoZSBganNvbmxpdGVgIHBhY2thZ2UgYWxvd3MgeW91IHRvIGNvbnZlcnQgdGhlIGRhdGEgZnJvbSBgSlNPTmAgKG9mdGVuIHVzZWQgYnkgQVBJcykgdG8gYSBkaWZmZXJldCBmb3JtYXQgdGhhdCBpcyBlYXNpZXIgdG8gd29yayB3aXRoLgoKQVBJcyB0eXBpY2FsbHkgcmVxdWlyZSBhIHBhc3N3b3JkIG9yIGtleSB0byBnYWluIGFjY2Vzcy4gVGh1cyB0aGUgYGh0dHJgIHBhY2thZ2UgaGVscHMgdG8gYXV0aGVudGljYXRlIHlvdXIgZGF0YSByZXF1ZXN0LiBPZnRlbiB0aGVzZSBrZXlzIGFyZSBzb21ldGhpbmcgdGhhdCB5b3UgZG8gbm90IHdhbnQgdG8gc2hhcmUsIHVubGVzcyB0aGUgQVBJIGlzIHB1YmxpYy4KCkluIG91ciBjYXNlIHRoZSBbQVBJXShodHRwczovL2FyY29zLWFwaS5leHQubmlsZS53b3Jrcy9fX3N3YWdnZXJfXy8pIGlzIGluZGVlZCBwdWJsaWMsIGFuZCBjdXJyZW50bHkgInVPNEVLNkkiIGlzIHB1YmxpY2x5IHB1Ymxpc2hlZCBhcyBhIGtleSB0byB1c2Ugb24gdGhlIFtnaXRodWIgcGFnZV0oaHR0cHM6Ly9naXRodWIuY29tL3dwaW52ZXN0aWdhdGl2ZS9hcmNvcykgZm9yIHRoZSBgYXJjb3NgIHBhY2thZ2UuIFdlIHdpbGwgdXNlIHRoYXQgaGVyZSB0byBhY2Nlc3MgdGhlIEFQSS4KCgojIyBQb3B1bGF0aW9uIERhdGEKCldlIGFyZSBpbnRlcmVzdGVkIGluIHRoZSBjb3VudHkgbGV2ZWwgZGF0YSAtIGZpcnN0IGxldCdzIGdldCB0aGUgcG9wdWxhdGlvbiBkYXRhLiBXZSBjYW4gYWNjZXNzIGl0IGJ5OgoKMSkgUHJlc3NpbmcgdGhlIGBHRVRgIGJ1dHRvbiBvbiB0aGUgQVBJLgoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJnZXQucG5nIikpCgpgYGAKCjIpIFByZXNzaW5nIHRoZSAiVHJ5IGl0IG91dCIgYnV0dG9uLgoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJ0cnlpdG91dC5wbmciKSkKYGBgCgozKSBFbnRlcmluZyB0aGUga2V5ICh3aGljaCB3ZSBnb3QgZnJvbSBbaGVyZV0oW2dpdGh1YiBwYWdlXShodHRwczovL2dpdGh1Yi5jb20vd3BpbnZlc3RpZ2F0aXZlL2FyY29zKSkpLgoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJrZXkucG5nIikpCmBgYAoKNCkgQ2xpY2tpbmcgdGhlICJFeGVjdXRlIiBidXR0b24uCgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgImV4ZWN1dGUucG5nIikpCmBgYAoKVGhpcyBnaXZlcyB1cyB0aGUgZm9sbG93aW5nIG91dHB1dDoKCmBjdXJsIC1YIEdFVCAiaHR0cHM6Ly9hcmNvcy1hcGkuZXh0Lm5pbGUud29ya3MvdjEvY291bnR5X3BvcHVsYXRpb24/a2V5PXVPNEVLNkkiIC1IICAiYWNjZXB0OiBhcHBsaWNhdGlvbi9qc29uImAKCldlIGNhbiBjb3B5IHRoZSBVUkwgc2VjdGlvbiBgImh0dHBzOi8vYXJjb3MtYXBpLmV4dC5uaWxlLndvcmtzL3YxL2NvdW50eV9wb3B1bGF0aW9uP2tleT11TzRFSzZJImAgYW5kIHVzZSBpdCBpbiB0aGUgYEdFVCgpYCBmdW5jdGlvbiBvZiB0aGUgYGh0dHJgIHBhY2thZ2UgOgoKYGBge3J9CmNvdW50eV9wb3BfanNvbjwtaHR0cjo6R0VUKHVybCA9ICJodHRwczovL2FyY29zLWFwaS5leHQubmlsZS53b3Jrcy92MS9jb3VudHlfcG9wdWxhdGlvbj9rZXk9dU80RUs2SSIpCmBgYAoKSWYgd2UgbmVlZGVkIHRvIHNwZWNpZnkgYSB1c2VybmFtZSBhbmQgcGFzc3dvcmQsIHdlIHdvdWxkIGRvIHNvIHVzaW5nIHRoZSBgYXV0aGVudGljYXRlKClgIGZ1bmN0aW9uIG9mIHRoZSBgaHR0cmAgcGFja2FnZSB3aXRoaW4gdGhlIGBHRVRgIGZ1bmN0aW9uLiBUaGUgYGF1dGhlbnRpY2F0ZSgpYCBmdW5jdGlvbiB0YWtlcyBgdXNlcmAsIGBwYXNzd29yZGAgYW5kIGB0eXBlYCBhcmd1bWVudHMuCgpIZXJlIGlzIGFuIGV4YW1wbGU6CgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpHRVQodXJsID0gImh0dHBzOi8vZXhhbXBsZVVSTCIsIGF1dGhlbnRpY2F0ZSh1c2VyID0gInVzZXJuYW1lIiwgcGFzc3dvcmQgPSAicGFzc3dvcmQiLCB0eXBlID0gImJhc2ljIikpCmBgYAoKVGhlIGRlZmF1bHQgdHlwZSBpcyBgImJhc2ljImAgYW5kIHR5cGNhbGx5IHdoYXQgaXMgbmVlZGVkLgoKTm93IHRoYXQgd2UgaGF2ZSB1c2VkIHRoZSBgR0VUYCBmdW5jdGlvbiwgd2UgaGF2ZSBhIFtKYXZhU2NyaXB0IE9iamVjdCBOb3RhdGlvbiAoSlNPTildKGh0dHBzOi8vZmlsZWluZm8uY29tL2V4dGVuc2lvbi9qc29uIzp+OnRleHQ9QSUyMEpTT04lMjBmaWxlJTIwaXMlMjBhLHdlYiUyMGFwcGxpY2F0aW9uJTIwYW5kJTIwYSUyMHNlcnZlci4pIGZpbGUgb2YgdGhlIGRhdGEuIAoKSlNPTiBmaWxlcyBhcmUgW2xpZ2h0d2VpZ2h0XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaWdodHdlaWdodF9wcm9ncmFtbWluZ19sYW5ndWFnZSkgbWVhbmluZyB0aGF0IHRoZXkgZG9uJ3QgdGFrZSB1cCBtdWNoIG1lbW9yeSBhbmQgdGhleSBhcmUgaHVtYW4gcmVhZGlibGUgZmlsZXMgdG8gbWFrZSB0cmFuc21pdHRpbmcgZGF0YSBmcm9tIHdlYnNpdGVzIGVhc2llci4KCmBgYHtyfQpjb3VudHlfcG9wX2pzb24KYGBgCgoKSGVyZSB3ZSBjYW4gc2VlIHRoYXQgdGhlIG9iamVjdCBjYWxsZWQgYGNvdW50eWpzb25gIGlzIGEgYGpzb25gIG9iamVjdC4gWW91IHdpbGwgYWxzbyBzZWUgdGhhdCB0aGUgYFNhdHVzYCBpcyBgMjAwYCwgd2hpY2ggbWVhbnMgdGhhdCB3ZSB3ZXJlIHN1Y2Vzc2Z1bCBpbiByZXRyZWl2aW5nIHRoZSBkYXRhIGZyb20gdGhlIEFQSS4KCk5vdyB3ZSBjYW4gdXNlIHRoZSBgY29udGVudCgpYCBmdW50aW9uIG9mIHRoZSBgaHR0cmAgcGFja2FnZSB0byBleHRyYWN0IHRoZSB0ZXh0IGZyb20gdGhlIGZpbGU6CgpgYGB7cn0KY291bnR5X3BvcF90ZXh0IDwtaHR0cjo6Y29udGVudChjb3VudHlfcG9wX2pzb24sICJ0ZXh0IikKYGBgCgpUaGlzIHdpbGwgYmUgYSB2ZXJ5IGxhcmdlIHN0cmluZyBhdCB0aGlzIHBvaW50LCB3ZSBjYW4gdGFrZSBhIGxvb2sgYXQgcGFydCBvZiBpdCBieSB1c2luZyB0aGUgYHN0cl9zdWIoKWAgZnVuY3Rpb24gb2YgdGhlIGBzdHJpbmdyYCBwYWNrYWdlLiBJbiB0aGlzIGNhc2Ugd2Ugd2lsbCBvbmx5IGxvb2sgYXQgdGhlIGZpcnN0IDQwMCBjaGFyYWN0ZXJzLgoKV2hhdCBpcyBhIHN0cmluZyBvciBhIGNocmFjdGVyPwoKKioqCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSBmb3IgYW4gZXhwbGFuYXRpb24gYWJvdXQgY2hhcmFjdGVyIHN0cmluZ3MgaWYgeW91IGFyZSBub3QgeWV0IGZhbWlsaWFyIDwvc3VtbWFyeT4KClRoZXJlIGFyZSBzZXZlcmFsIGNsYXNzZXMgb2YgZGF0YSBpbiBSIHByb2dyYW1taW5nLiAKQ2hhcmFjdGVyIGlzIG9uZSBvZiB0aGVzZSBjbGFzc2VzLiAKQSBjaGFyYWN0ZXIgc3RyaW5nIGlzIGFuIGluZGl2aWR1YWwgZGF0YSB2YWx1ZSBtYWRlIHVwIG9mIGNoYXJhY3RlcnMuIApUaGlzIGNhbiBiZSBhIHBhcmFncmFwaCwgbGlrZSB0aGUgbGVnZW5kIGZvciB0aGUgdGFibGUsIG9yIGl0IGNhbiBiZSBhIHNpbmdsZSBsZXR0ZXIgb3IgbnVtYmVyIGxpa2UgdGhlIGxldHRlciBgImEiYCBvciB0aGUgbnVtYmVyIGAiMyJgLiAKCklmIGRhdGEgYXJlIG9mIGNsYXNzIGNoYXJhY3RlciwgdGhhbiB0aGUgbnVtZXJpYyB2YWx1ZXMgd2lsbCBub3QgYmUgcHJvY2Vzc2VkIGxpa2UgYSBudW1lcmljIHZhbHVlIGluIGEgbWF0aGVtYXRpY2FsIHNlbnNlLiAKCjwvZGV0YWlscz4KKioqCgpgYGB7cn0Kc3RyaW5ncjo6c3RyX3N1Yihjb3VudHlfcG9wX3RleHQsIHN0YXJ0ID0gMSwgZW5kID0gNDAwKQpgYGAKCgpOb3cgdG8gZ2V0IHRoZSBkYXRhIGludG8gYSBtb3JlIHJlYWRpYmxlIGZvcm1hdCAsIHdlIGNhbiB1c2UgdGhlIGBmcm9tSlNPTigpYCBmdW5jdGlvbiBvZiB0aGUgYGpzb25saXRlYCBwYWNrYWdlIGFuZCBhZ2FpbiBjcmVhdGUgYSB0aWJibGUgb2YgdGhlIGRhdGEgdXNpbmcgYGFzX3RpYmJsZSgpYCAKCmBgYHtyfQpjb3VudHlfcG9wIDwtIGpzb25saXRlOjpmcm9tSlNPTihjb3VudHlfcG9wX3RleHQsIGZsYXR0ZW4gPSBUUlVFKQpjb3VudHlfcG9wIDwtIGFzX3RpYmJsZShjb3VudHlfcG9wKQpgYGAKCldlIGNhbiB1c2UgdGhlIGBnbGltcHNlKClgIGZ1bmN0aW9uIGFuZCB0aGUgYGRpc3RpbmN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gZ2V0IGEgYmV0dGVyIHNlbnNlIG9mIHRoZSBkYXRhLiBUaGUgYGRpc3RpbmN0KClgIGZ1bmN0aW9uIGFsbG93cyB1cyB0byB0YWtlIGEgbG9vayBhdCB0aGUgdW5pcXVlIHZhbHVlcyBvZiB0aGUgYHllYXJgIHZhcmlhYmxlLgoKYGBge3J9CmRwbHlyOjpnbGltcHNlKGNvdW50eV9wb3ApCmRwbHlyOjpkaXN0aW5jdChjb3VudHlfcG9wLHllYXIpCmBgYAoKSXQgbG9va3MgbGlrZSB3ZSBoYXZlIHRoZSBmdWxsIGRhdGEgZnJvbSAyMDA2LTIwMTQuCgoKYGBge3IsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQp3cml0ZS5jc3YoY291bnR5X3BvcCwgZmlsZSA9IGhlcmU6OmhlcmUoImRhdGEiLCAiY291bnR5X3BvcF9hcmNvcy5jc3YiKSkKc2F2ZShjb3VudHlfcG9wLCBmaWxlID0gIGhlcmU6OmhlcmUoImRhdGEiLCAiY291bnR5X3BvcF9hcmNvcy5yZGEiKSkKYGBgCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpsb2FkKGhlcmU6OmhlcmUoImRhdGEiLCAiY291bnR5X3BvcF9hcmNvcy5yZGEiKSkKYGBgCgpXZSBhcmUgYWxzbyBpbnRlcmVzdGVkIGluIG9waW9pZCBwaWxsIHNoaXBtZW50IGRhdGEgYXQgdGhlIGNvdW50eSBsZXZlbC4gCgoKCiMjIEFubnVhbCBTaGlwbWVudCBEYXRhCgpIZXJlIGlzIHRoZSByZXN1bHQgb2YgdGhlIHNhbWUgc3RlcHMgdXNpbmcgdGhlIEFQSSBmb3IgdGhlIGNvbWJpbmVkX2NvdW50eV9hbm51YWwgZGF0YToKCmBjdXJsIC1YIEdFVCAiaHR0cHM6Ly9hcmNvcy1hcGkuZXh0Lm5pbGUud29ya3MvdjEvY29tYmluZWRfY291bnR5X2FubnVhbD9rZXk9dU80RUs2SSIgLUggICJhY2NlcHQ6IGFwcGxpY2F0aW9uL2pzb24iYAoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpTZWUgaWYgeW91IGNhbiBmaXggaW1wb3J0IHRoZSBkYXRhIHdpdGhvdXQgbG9va2luZyBhdCB0aGUgY29kZSBmb3IgdGhlIHBvcHVsYXRpb24gZGF0YS4KCiMjIyMKCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBjb2RlLiA8L3N1bW1hcnk+CgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpjb3VudHlfYW5udWFsX2pzb248LWh0dHI6OkdFVCh1cmwgPSAgImh0dHBzOi8vYXJjb3MtYXBpLmV4dC5uaWxlLndvcmtzL3YxL2NvbWJpbmVkX2NvdW50eV9hbm51YWw/a2V5PXVPNEVLNkkiKQpjb3VudHlfYW5udWFsX2pzb25fdGV4dCA8LWh0dHI6OmNvbnRlbnQoY291bnR5X2FubnVhbF9qc29uLCAidGV4dCIpCmNvdW50eV9hbm51YWwgPC0ganNvbmxpdGU6OmZyb21KU09OKGNvdW50eV9hbm51YWxfanNvbl90ZXh0LCBmbGF0dGVuID0gVFJVRSkKYW5udWFsRG9zYWdlIDwtIHRpYmJsZTo6YXNfdGliYmxlKGNvdW50eV9hbm51YWwpCmBgYAoKPC9kZXRhaWxzPgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgZXZhbCA9IEZBTFNFfQp3cml0ZS5jc3YoYW5udWFsRG9zYWdlLCBmaWxlID0gaGVyZTo6aGVyZSgiZGF0YSIsICJjb3VudHlfYW5udWFsLmNzdiIpKQpzYXZlKGFubnVhbERvc2FnZSwgZmlsZSA9ICBoZXJlOjpoZXJlKCJkYXRhIiwgImNvdW50eV9hbm51YWwucmRhIikpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CmxvYWQoaGVyZTo6aGVyZSgiZGF0YSIsICJjb3VudHlfYW5udWFsLnJkYSIpKQpgYGAKCgpOb3cgbGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIGRhdGE6CmBgYHtyfQpnbGltcHNlKGFubnVhbERvc2FnZSkKZGlzdGluY3QoYW5udWFsRG9zYWdlLCB5ZWFyKQoKYGBgCgpMb29rcyBsaWtlIHdlIGhhdmUgdGhlIHNhbWUgeWVhcnMgb2YgZGF0YS4KCgpgYGB7ciwgZXZhbCA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CiMgV2UgYWxzbyByZXRyaWV2ZWQgdGhlIG1vbnRobHkgZGF0YSBmb3IgaW5zdHJ1Y3RvcnMgd2hvIHdpc2ggdG8gdXNlIHRoaXMgZGF0YQpjb3VudHlqc29uIDwtIGh0dHI6OkdFVCh1cmwgPSAiaHR0cHM6Ly9hcmNvcy1hcGkuZXh0Lm5pbGUud29ya3MvdjEvY29tYmluZWRfY291bnR5X21vbnRobHk/a2V5PXVPNEVLNkkiKQpjb3VudHlqc29uX3RleHQgPC1odHRyOjpjb250ZW50KGNvdW50eWpzb24sICJ0ZXh0IikKY291bnR5IDwtIGpzb25saXRlOjpmcm9tSlNPTihjb3VudHlqc29uX3RleHQsIGZsYXR0ZW4gPSBUUlVFKQptb250aGx5RG9zYWdlIDwtIHRpYmJsZTo6YXNfdGliYmxlKGNvdW50eSkKYGBgCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gRkFMU0V9CndyaXRlLmNzdihtb250aGx5RG9zYWdlLCBmaWxlID0gaGVyZTo6aGVyZSgiZGF0YSIsICJjb3VudHlfbW9udGhseS5jc3YiKSkKc2F2ZShtb250aGx5RG9zYWdlLCBmaWxlID0gIGhlcmU6OmhlcmUoImRhdGEiLCAiY291bnR5X21vbnRobHkucmRhIikpCmBgYAoKYGBge3IsIGVjaG8gPSBGQUxTRX0KbG9hZChoZXJlOjpoZXJlKCJkYXRhIiwgImNvdW50eV9tb250aGx5LnJkYSIpKQpgYGAKCgojICoqRGF0YSBFeHBsb3JhdGlvbioqCioqKgoKTm93IGxldCdzIHRha2UgYSBkZWFwZXIgbG9vayBhdCB0aGUgZGF0YSB0byBzZWUgaWYgd2UgaGF2ZSBhbnkgbWlzc2luZyBkYXRhIHVzaW5nIHRoZSBgbmFuaWFyYCBwYWNrYWdlLgoKV2UgY2FuIHVzZSB0aGUgYHZpc19taXNzKClgIGZ1bmN0aW9uIHRvIGNyZWF0ZSBhIHBsb3Qgb2YgbWlzc2luZyBkYXRhLgoKTGV0J3Mgc3RhcnQgd2l0aCB0aGUgbGFuZCBhcmVhIGRhdGEuCmBgYHtyfQpuYW5pYXI6OiB2aXNfbWlzcyhsYW5kKQpgYGAKTG9va3MgbGlrZSB0aGVyZSBpcyBubyBtaXNzaW5nIGRhdGEuCgpIb3cgYWJvdXQgdGhlIHBvcHVsYXRpb24gZGF0YToKCmBgYHtyfQp2aXNfbWlzcyhjb3VudHlfcG9wKQpgYGAKCldlIGFwcGVhciB0byBiZSBtaXNzaW5nIHNvbWUgdmFsdWVzIGZvciB0aGUgYE5hbWVgIGFuZCBgdmFyaWFibGVgIGRhdGEsIGJ1dCB3ZSBkb25gdCBpbnRlbmQgdG8gdXNlIHRoZXNlLCBzbyB0aGlzIHNob3VsZCBiZSBvay4gSXQgaXMgaG93ZXZlciBhIGdvb2QgaWRlYSB0byBjaGVjayB0aGVzZSByb3dzIHRvIHNlZSBpZiBhbnl0aGluZyBzdHJhbmdlIGlzIGhhcHBlbmluZy4KCkxldCdzIHVzZSB0aGUgYGZpbHRlcigpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIGFuZCB0aGUgYGlzLm5hKClgIGJhc2UgZnVuY3Rpb24gdG8gc2VlIG1vcmUgYWJvdXQgdGhlIGRhdGEgdGhhdCBkb2VzIG5vdCBoYXZlIGNvdW50eWZpcHMgY29kZXMuCgpXZSB3aWxsIGFsc28gc3RhcnQgdXNpbmcgdGhlIGAlPiVgIHBpcGUgb2YgdGhlIGBtYWdyaXR0cmAgcGFja2FnZSBmb3Igb3VyIGFzc2lnbm1lbnRzLgoKCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSBpZiB5b3UgYXJlIHVuZmFtaWxpYXIgd2l0aCBwaXBpbmcgaW4gUiwgd2hpY2ggdXNlcyB0aGlzIGAlPiVgIG9wZXJhdG9yPC9zdW1tYXJ5PiAgCgoKQnkgW3BpcGluZ10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ3JpdHRyL3ZpZ25ldHRlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHdlIG1lYW4gdXNpbmcgdGhlIGAlPiVgIHBpcGUgb3BlcmF0b3Igd2hpY2ggaXMgYWNjZXNzaWJsZSBhZnRlciBsb2FkaW5nIHRoZSBgdGlkeXZlcnNlYCBvciBzZXZlcmFsIG9mIHRoZSBwYWNrYWdlcyB3aXRoaW4gdGhlIHRpZHl2ZXJzZSBsaWtlIGBkcGx5cmAgYmVjYXVzZSB0aGV5IGxvYWQgdGhlIFtgbWFncml0dHJgIHBhY2thZ2VdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYWdyaXR0ci92aWduZXR0ZXMvbWFncml0dHIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifS4gClRoaXMgYWxsb3dzIHVzIHRvIHBlcmZvcm0gbXVsdGlwbGUgc2VxdWVudGlhbCBzdGVwcyBvbiBvbmUgZGF0YSBpbnB1dC4gCgoqKioKCjwvZGV0YWlscz4gCgpgYGB7cn0KY291bnR5X3BvcCAlPiUgZmlsdGVyKGlzLm5hKE5BTUUpKQpgYGAKClRoaXMgbG9va3Mgb2suIFNvIGxldCdzIG5vdyBtb3ZlIG9uIHRvIHRoZSBERUEgZGF0YS4KYGBge3J9CnZpc19taXNzKGFubnVhbERvc2FnZSkKYGBgCgpJbnRlcmVzdGluZywgd2UgYXBwZWFyIHRvIGJlIG1pc3NpbmcgYGNvdW50eWZpcHNgIGNvZGVzIGZvciBhIHNtYWxsIHBlcmNlbnRhZ2Ugb2Ygb3VyIGFubnVhbCBkYXRhLgoKCkxldCdzIHRha2UgYSBsb29rIGF0IHRoaXMgZGF0YToKCmBgYHtyfQphbm51YWxEb3NhZ2UgJT4lIGZpbHRlcihpcy5uYShjb3VudHlmaXBzKSkKYGBgCgoKSXQgbG9va3MgbGlrZSB0aGUgbWlzc2luZyBkYXRhIGlzIGRhdGEgZm9yIFB1ZXJ0byBSaWNvIC0gaXQgbWFrZXMgc2Vuc2UgdGhhdCBpdCBkb2Vzbid0IGhhdmUgY291bnR5ZmlwcyBjb2Rlcy4KCkxldCdzIHNlZSBpZiB0aGVyZSBpcyBhbnkgZGF0YSBvdGhlciB0aGFuIGRhdGEgZm9yIFB1ZXJ0byBSaWNvIHRoYXQgaXMgYWxzbyBtaXNzaW5nIGBjb3VudHlmaXBzYCB2YWx1ZXMuIFdlIGNhbiB1c2UgdGhlIGAhPWAgb3BlcmF0b3Igd2hpY2ggaW5kaWNhdGVzIG5vdCBlcXVhbCB0by4KCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQphbm51YWxEb3NhZ2UgJT4lIGZpbHRlcihpcy5uYShjb3VudHlmaXBzKSkgJT4lCiBmaWx0ZXIoQlVZRVJfU1RBVEUgIT0gIlBSIikKYGBgCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyLCBlY2hvID0gRkFMU0V9CmFubnVhbERvc2FnZSAlPiUgZmlsdGVyKGlzLm5hKGNvdW50eWZpcHMpKSAlPiUKIGZpbHRlcihCVVlFUl9TVEFURSAhPSAiUFIiKSAlPiUKICAjIHRoaXMgYWxsb3dzIHVzIHRvIHNob3cgdGhlIGZ1bGwgb3V0cHV0IGluIHRoZSByZW5kZXJlZCBybWFya2Rvd24KIHByaW50KG4gPSAxZTQpCmBgYAojIyMjCgpJdCBsb29rcyBsaWtlIHRoZXJlIGlzIGFsc28gZGF0YSBmb3Igb3RoZXIgdGVycml0b3JpZXMgaW4gdGhlIGRhdGFzZXQsIGFzIHdlbGwgYXMgc29tZSBjb3VudGllcyB3aXRoIG5vIG5hbWUuCgpGb3Igc29tZSByZWFzb24gdGhlIHJvd3MgZm9yIHRoZSBNb250Z29tZXJ5IGNvdW50eSBvZiBBcmthbnNhIGFyZSBhbHNvIG1pc3NpbmcgYSBgY291bnR5Zmlwc2AgdmFsdWUuCgpgYGB7cn0KYW5udWFsRG9zYWdlICU+JSBmaWx0ZXIoaXMubmEoY291bnR5ZmlwcykpICU+JQogZmlsdGVyKEJVWUVSX1NUQVRFID09ICJBUiIpCmBgYAoKCkFjY29yZGluZyB0byB0aGlzIFt3ZWJzaXRlXShodHRwczovL3d3dy5ucmNzLnVzZGEuZ292L3dwcy9wb3J0YWwvbnJjcy9kZXRhaWwvbmF0aW9uYWwvaG9tZS8/Y2lkPW5yY3MxNDNfMDEzNjk3KSB0aGllIGZJUFMgY29kZSBpcyAwNTA5Ny4KCgpXZSB3aWxsIHVwZGF0ZSB0aGVzZSB2YWx1ZXMgaW4gdGhlIG5leHQgc2VjdGlvbi4KCgojICoqRGF0YSBXcmFuZ2xpbmcqKgoqKioKCiMjIENsZWFuaW5nIGxhbmQgZGF0YQoKV2Ugd2FudCB0aGUgYExORDExMDIxMERgIGNvbHVtbiB3aGljaCBpcyB0aGUgZGF0YSBmcm9tIHRoZSB5ZWFyIDIwMTAuCgpMTkQgPSBMYW5kIEFyZWEKMTEwID0gdW5pdCBzcXVhcmUgbWlsZXMgKHN1Ymdyb3VwLWNvZGUgb2YgdGhlIGdyb3VwKSAqIGF2b2NhZG8gSSBmb3VuZCB0aGlzIHNvbWVod2VyZSBlbHNlLi4gdGhlIGNlbnN1cyBpbmZvIHdhcyB2YXVnZSB3b3VsZCBsaWtlIHRvIGNvbmZpcm0gdGhhdCB0aGF0IGlzIGluZGVlZCB3aGF0IHRoZSBzdWdyb3VwIGNvZGUgc2hvd3MgdXMKMiA9IGNlbnR1cnkKMTAgPSAyMDEwIChiYXNlZCBvbiB0aGUgY2VudHVyeSkKRCA9IERhdGEKClRodXMgd2UgY2FuIHNlbGVjdCBqdXN0IHRoZSBjb3VudHkgbmFtZXMsIHRoZSBjb3VudHkgbnVtZXJpYyBjb2RlcywgYW5kIHRoZSBgTE5EMTEwMjEwRGBjb2x1bW4gYnkgdXNpbmcgdGhlIGBzZWxlY3QoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4KCmBgYHtyfQpjb3VudHlfYXJlYSA8LSBsYW5kICU+JSBzZWxlY3QoQXJlYW5hbWUsIFNUQ09VLCBMTkQxMTAyMTBEKQpjb3VudHlfYXJlYQpgYGAKCgojIyBVcGRhdGluZyBgY291bnR5Zmlwc2AKCldlIHdpbGwgdXNlIHRoZSBgY2FzZV93aGVuKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgcmVjb2RlIHRoZSBgTkFgIHZhbHVlcyBmb3IgdGhlIHJvd3MgZm9yIHRoZSBgTU9OR09NRVJZYCBjb3VudHkgb2YgYEFSYCB0byBiZSBgMDUwOTdgLiBGaXJzdCB3ZSBuZWVkIHRvIHNwZWNpZnkgZm9yIHRoZXNlIHBhcnRpY3VsYXIgcm93cy4gQmVjdWFzZSB0aGVyZSBNb250Z29tZXJ5IG1heSBiZSBhIGNvdW50eSBuYW1lIGluIG90aGVyIHN0YXRlcywgd2UgbmVlZCB0byBldmFsdWF0ZSB3aGVuIHRoZSBgQlVZRVJfU1RBVEVgIGlzIGBBUmAgYW5kIHdoZW4gdGhlIGBCVVlFUl9DT1VOVFlgIGlzIGBNT05UR09NRVJZYC4gV2Ugd2lsbCB1c2UgdGhlIGAmYCBvcHBlcmF0b3IgdG8gaW5kY2F0ZSB0aGF0IGJvdGggY29uZGl0aW9ucyBtdXN0IGJlIHRydWUuIFdlIHdpbGwgdGhlbiByZWNvZGUgdGhlIGBjb3V0cnlmaXBzYCB2YWx1ZXMgZm9yIHRoZXNlIHJvd3MgdG8gYmUgYCIwNTA5NyJgIHVzaW5nIHRoZSBgfmAgc3ltYm9sLiBBbGwgb3RoZXIgdmFsdWVzIG5lZWQgdG8gc3RheSB0aGUgc2FtZS4gVGh1cyB3ZSBuZWVkIHRvIHVzZSBgVFJVRSB+YCB0byByZWNvZGUgYWxsIHRoZSBvdGhlciBgY291bnR5Zmlwc2AgdmFsdWVzIHRvIHdoYXQgdGhleSBjdXJyZW50bHkgYXJlLiBPdGhlcndpc2UgdGhlc2Ugd291bGQgYXV0bWF0aWNhbGx5IGJlIGBOQWAuCgpXZSBhcmUgYWxzbyBnb2luZyB0byB1c2UgYSBzcGVjaWFsIHBpcGUgb3BlcmF0b3IgZnJvbSB0aGUgW2BtYWdyaXR0cmAgcGFja2FnZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ3JpdHRyL3ZpZ25ldHRlcy9tYWdyaXR0ci5odG1sKSBjYWxsZWQgdGhlIGNvbXBvdW5kIGFzc2lnbm1lbnQgcGlwZS1vcGVyYXRvciBvciBzb21ldGltZXMgdGhlIGRvdWJsZSBwaXBlIG9wZXJhdG9yLiAKClRoaXMgYWxsb3dzIHVzIHRvIHVzZSB0aGUgYGFubnVhbERvc2FnZWAgYXMgb3VyIGlucHV0IGFuZCByZWFzc2lnbiBpdCBhdCB0aGUgZW5kIGFmdGVyIGFsbCB0aGUgc3Vic2VxdWVudCBzdGVwcyBoYXZlIGJlZW4gcGVyZm9ybWVkLCBhbHRob3VnaCBpbiB0aGlzIGNhc2UgaXQgaXMgb25seSBvbmUgc3RlcC4KCmBgYHtyfQoKYW5udWFsRG9zYWdlICU8PiUgCiAgbXV0YXRlKGNvdW50eWZpcHMgPSBjYXNlX3doZW4oQlVZRVJfU1RBVEUgPT0gIkFSIiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQlVZRVJfQ09VTlRZID09ICJNT05UR09NRVJZIiB+IGFzLmNoYXJhY3RlcigiMDUwOTciKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBjb3VudHlmaXBzKSkKCmBgYAoKTm93IHdlIGNhbiBjaGVjayB0aGF0IHdlIGluZGVlZCBmaXhlZCBvdXIgZGF0YS4KCmBgYHtyfQphbm51YWxEb3NhZ2UgJT4lIAogIGZpbHRlcihpcy5uYShjb3VudHlmaXBzKSkgJT4lCiAgZmlsdGVyKEJVWUVSX1NUQVRFID09ICJBUiIpCgphbm51YWxEb3NhZ2UgJT4lIAogIGZpbHRlcihCVVlFUl9DT1VOVFkgPT0gIk1PTlRHT01FUlkiKSAlPiUKICBmaWx0ZXIoQlVZRVJfU1RBVEUgPT0gIkFSIikKYGBgCgpHcmVhdCEgV2UgZml4ZWQgaXQuCgoKCgoKT0ssIHdlIGFsc28gaGFkIHNvbWUgcm93cyB0aGF0IGRpZG4ndCBoYXZlIGNvdW50eSBuYW1lcyBiZWNhdXNlIHRoZXkgd2VyZSBqdXN0IG1pc3Npbmcgb3IgdGhlIGRhdGEgd2FzIGZvciBVUyB0ZXJyaXRvcmllcy4gV2Ugd2lsbCByZW1vdmUgdGhlIHZhbHVlcyB0aGF0IGRvbnQgaGF2ZSBjb3VudHkgbmFtZXMuCgpGaXJzdCBsZXQncyB0YWtlIGEgbG9vayBhdCB0aGVtIGFnaWFuLgoKYGBge3J9CmFubnVhbERvc2FnZSAlPiUgZmlsdGVyKGlzLm5hKEJVWUVSX0NPVU5UWSkpCmBgYAoKV2UgY2FuIGZpbHRlciBvdXQgdGhlc2UgdmFsdWVzIGJ5IHVzaW5nIHRoZSBgIWAgZXhjbGFtYXRpb24gbWFyayBiZWZvcmUgdGhlIGBpcy5uYSgpYCBmdW5jdGlvbi4KCmBgYHtyfQoKYW5udWFsRG9zYWdlICU8PiUgIGZpbHRlcighaXMubmEoQlVZRVJfQ09VTlRZKSkKYGBgCgpBbmQgbm93IGxldCdzIGNoZWNrIHRoYXQgdGhlc2UgYE5BYCB2YWx1ZXMgYXJlIGdvbmU6CgpgYGB7cn0KYW5udWFsRG9zYWdlICU+JSBmaWx0ZXIoaXMubmEoQlVZRVJfQ09VTlRZKSkKCmBgYAoKTGV0J3MgY2hlY2sgaWYgb3VyIGxhbmQgYXJlYSBkYXRhIGhhcyBpbmZvcm1hdGlvbiBmb3IgVVMgdGVycml0b3JpZXMuIElmIG5vdCwgd2Ugd2lsbCByZW1vdmUgdGhlIGRhdGEgZm9yIHRoZSB0ZXJyaXRvcmllcyBpbiBvdXIgYGFubnVhbERvc2FnZWAgZGF0YS4gSG93ZXZlciwgdGhpcyB3b3VsZCBiZSB2ZXJ5IGludGVyZXN0aW5nIGFuZCBpbXBvcmF0YW50IHRvIGludmVzdGlnYXRlLiBXZSBjYW4gdXNlIHRoZSBgc3RyX2RldGVjdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UsIHdoaWNoIGNvbnRhaW5zIGxvdHMgb2YgZnVuY3Rpb25zIGZvciBsb29raW5nIGZvciBwYXR0ZXJucyBpbiBjaGFyYWN0ZXIgc3RyaW5ncywgdG8gbG9vayBmb3IgZGF0YSBmcm9tIFB1ZXJ0byBSaWNvLiAKClRoZSBgc3RyX2RldGVjdCgpYCBmdW5jdGlvbiBhbGxvd3MgdXMgdG8gbG9vayBmb3IgYSBwYXJ0aWN1bGFyIHBhdHRlcm4uIEl0IGRvZXMgbm90IGhhdmUgdG8gYmUgdGhlIGZ1bGwgdmFsdWUsIHRoZXJlIGNhbiBiZSBhIHBhcnRpYWwgbWF0Y2guIFRodXMgd2UgY2FuIGxvb2sgdG8gc2VlIGlmIHRoZXJlIGFyZSBhbnkgYFBSYCBzdHJpbmdzIHdpdGhpbmcgdGhlIHZsYXVlcyBvZiB0aGUgdGhlIGBBcmVhbmFtZWAgdmFyaWFibGUuIAoKYGBge3J9CmNvdW50eV9hcmVhICU+JSBmaWx0ZXIoc3RyX2RldGVjdChzdHJpbmcgPSBBcmVhbmFtZSwgcGF0dGVybiA9ICJQUiIpKQpgYGAKCllvdSBjYW4gc2VlIHVzaW5nIGEgZGlmZmVyZW50IGFiYnJldmlhdGlvbiwgdGhhdCB0aGlzIGNvZGUgZG9lcyBhcyBpbnRlbmRlZDoKCmBgYHtyfQpjb3VudHlfYXJlYSAlPiUgZmlsdGVyKHN0cl9kZXRlY3Qoc3RyaW5nID0gQXJlYW5hbWUsIHBhdHRlcm4gPSAiQVIiKSkKYGBgCgpPSywgc28gaXQgZG9lcyBtb3QgbG9vayBsaWtlIHRoZXJlIGlzIGFueSB0ZXJyaXRvcnkgbGFuZCBhcmVhIGRhdGEgaW4gdGhpcyBkYXRhc2V0LiBUaHVzIHdlIHdpbGwgYWxzbyByZW1vdmUgdGhlc2UgZnJvbSB0aGUgYGFubnVhbERvc2FnZWAgYW5kIGBtb250aGx5RG9zYWdlYCB0aWJibGVzLgoKIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4KCkRvIHlvdSByZWNhbGwgaG93IHRvIGRvIHRoaXM/CgoKIyMjIwoKCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGNvZGUuIDwvc3VtbWFyeT4KYGBge3J9CmFubnVhbERvc2FnZSAlPD4lIGZpbHRlcighaXMubmEoY291bnR5ZmlwcykpCmBgYAo8L2RldGFpbHM+IAoKCmBgYHtyfQpuYW5pYXI6OiB2aXNfbWlzcyhhbm51YWxEb3NhZ2UpCmBgYAoKR3JlYXQhIE5vdyB0aGVyZSBpcyBubyBtaXNzaW5nIGRhdGEgaW4gb3VyIGFubnVhbCBkYXRhLgoKCiMjIFJ1cmFsIGFuZCBVcmJhbiBDb3VudGllcwoKRGVmaW5pbmcgaWYgYSByZWdpb24gaXMgcnVyYWwgb3IgdXJiYW4gaXMgYWN0dWFsbHkgcXVpdGUgY29tcGxpY2F0ZWQgYXMgdGhlIG92ZXJhbGwgcG9wdWxhdGlvbiBjaGFuZ2VzLCB0aGUgc3RydWN0dXJlIG9mIG91ciB0b3ducyBhbmQgY2l0aWVzIGNoYW5nZXMsIGFuZCB0aGUgYWNjZXNzIGJldHdlZW4gZGlmZmVyZW50IGxvY2F0aW9ucyBjaGFuZ2VzIG92ZXIgdGltZS4gUGxlYXNlIHNlZSB0aGlzIFtyZXBvcnRdKGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L2dlby9wZGZzL3JlZmVyZW5jZS91YS9EZWZpbmluZ19SdXJhbC5wZGYpIGZvcm0gdGhlIFVTIENlbnN1cyBCZXVyZWF1IGFib3V0IHRoZSBoaXN0b3J5IG9mIHRoaXMgZGVmaW5pdGlvbi4gCgpBY2NvcmRpbmcgdG8gc2V2ZXJhbCBbZGVmaW5pdGlvbnNdKGh0dHBzOi8vd3d3Lmhyc2EuZ292L3J1cmFsLWhlYWx0aC9hYm91dC11cy9kZWZpbml0aW9uL2luZGV4Lmh0bWwpIC0gdXJiYW4gKiphcmVhcyoqIGFyZSBvZnRlbiBkZWZpbmVkIGFzIHRob3NlIHdpdGggZ3JlYXRlciB0aGFuIDUwLDAwMCBwZW9wbGUuIEhvd2V2ZXIsIHRoZXJlIGFyZSBhbHNvCltkZWZpbml0aW9uc10oaHR0cHM6Ly93d3cuZXJzLnVzZGEuZ292L3RvcGljcy9ydXJhbC1lY29ub215LXBvcHVsYXRpb24vcnVyYWwtY2xhc3NpZmljYXRpb25zL3doYXQtaXMtcnVyYWwvKSBvZiBydXJhbCBhcmVhcyBiZWluZyBiYXNlZCBvbiAgInBvcHVsYXRpb24gZGVuc2l0aWVzIG9mIGxlc3MgdGhhbiA1MDAgcGVvcGxlIHBlciBzcXVhcmUgbWlsZSBhbmQgcGxhY2VzIHdpdGggZmV3ZXIgdGhhbiAyLDUwMCBwZW9wbGUiLiBUeXBpY2FsbHkgY291bnRpZXMgYXJlIG1hZGUgdXAgb2YgbXVsdGlwbGUgYXJlYXMuIAoKVGhlIGNlbnN1cyBlc3RpbWF0ZXMgcnVyYWwgYW5kIHVyYmFuIGFyZWFzIGFyb3VuZCB0aGUgVVMgcmVsYXRpdmVseSBvZnRlbi4gSG93ZXZlciwgY2Vuc3VzIGNvbGxlY3Rpb25zIGFib3V0IHRoZXNlIG1lYXN1cmVzbWVudHMgZG9lcyBub3Qgb2NjdXIgZXZlcnkgeWVhci4KClRodXMgd2Ugd2lsbCBkZWZpbmUgYSBjb3VudHkgYXMgcnVyYWwgb3IgdXJiYW4gYmFzZWQgb24gdGhlIHBvcHVsYXRpb24gZGVuc2l0eSB1c2luZyB0aGUgVVNEQSBbZGVmaW5pdGlvbl0oKGh0dHBzOi8vd3d3LmVycy51c2RhLmdvdi90b3BpY3MvcnVyYWwtZWNvbm9teS1wb3B1bGF0aW9uL3J1cmFsLWNsYXNzaWZpY2F0aW9ucy93aGF0LWlzLXJ1cmFsLykpIHRoYXQgd2UgZGVzY3JpYmVkIGFib3ZlOgoKcnVyYWwgID0gcG9wdWxhdGlvbiBkZW5zaXRpZXMgb2YgbGVzcyB0aGFuIDUwMCBwZW9wbGUgcGVyIHNxdWFyZSBtaWxlLCBhcyB3ZWxsIGFzIHBsYWNlcyB3aXRoIGZld2VyIHRoYW4gMiw1MDAgcGVvcGxlICAgCiAgdWJhbiA9IHBvcHVsYXRpb25zIGRlbnNpdGllcyBvZiBncmVhdGVyIHRoYW4gNTAwIHBlb3BsZSBwZXIgc3F1YXJlIG1pbGUKCgpJZGVhbGx5IHdlIHdvdWxkIHdhbnQgbGFuZCBhcmVhIGZyb20gZWFjaCB5ZWFyLCBhcyB0aGVzZSBkbyBmbHVjdHVhdGUgYSBiaXQsIGhvd2V2ZXIsIHRoaXMgc2hvdWxkIGJlIGEgZGVjZW50IGFwcHJveGltYXRpb24gYXMgMjAxMCBpcyBpbiB0aGUgbWlkZGxlIG9mIG91ciB0aW1lIHNwYW4uCgpXZSB3aWxsIHRoZXJlZm9yZSBjYWxjdWxhdGUgdGhlIGRlbnNpdHkgYXMgdGhlIG51bWJlciBvZiBwZW9wbGUgcGVyIHNxdWFyZSBtaWxlIGJ5IGRpdmlkaW5nIHRoZSBwb3B1bGF0aW9uIHZhbHVlcyBieSB0aGUgbGFuZCBhcmVhIHZhbHVlcy4gVG8gZG8gc28gd2UgZmlyc3QgbmVlZCB0byBjb21iaW5lIG91ciBgY291bnR5X2FyZWFgIGFuZCBvdXIgYGNvdW50eV9wb3BgIGRhdGEgdG9nZXRoZXIuIEZpcnN0IHdlIHdhbnQgdG8gbWFrZSBzdXJlIHRoYXQgd2UgaGF2ZSBvbmUgY29sdW1uLCBpbiBvdXIgY2FzZSB0aGUgIGNvbHVtbiB0aGF0IGNvbnRhaW5zIHRoZSBudW1lcmljIGNvZGUgZm9yIHRoZSBjb3VudGllcywgaW4gdGhlIHNhbWUgZm9ybWF0IGFuZCB3aXRoIHRoZSBzYW1lIG5hbWUgaW4gYm90aCB0aGUgdGliYmxlcyB0aGF0IHdlIHdpc2ggdG8gY29tYmluZS4gCgpXZSBjYW4gdXNlIHRoZSBgcmVuYW1lKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gcmVuYW1lIHRoZSBgU1RDT1VgIGNvbHVtbiB0byBiZSBgY291bnR5Zmlwc2AuIFRoZSBuZXcgbmFtZSBpcyBhbHdheXMgbGlzdGVkIGZpcnN0IGJlZm9yZSB0aGUgb2xkIG5hbWUgd2l0aCB0aGlzIGZ1bmN0aW9uIGxpa2Ugc286IGByZW5hbWUobmV3X25hbWUgPSBvbGRfbmFtZSlgLgoKYGBge3J9CmNvdW50eV9hcmVhICU8PiUKICByZW5hbWUoY291bnR5ZmlwcyA9IFNUQ09VKQpgYGAKCgpXZSBjYW4gdXNlIHRoZSBgbXV0YXRlKClgIGZ1bnRpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBtYWtlIHRoZSBgY291bnR5Zmlwc2AgdmFyaWFibGUgYSBmYWN0b3IgaW4gYm90aCB0aWJibGVzLiAKCldoYXQgZXhhY3RseSBpcyBhIGZhY3Rvcj8KCioqKgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgZm9yIGFuIGV4cGxhbmF0aW9uIG9mIGRhdGEgY2xhc3NlcyBpbiBSIDwvc3VtbWFyeT4KClRoZXJlIGFyZSBzZXZlcmFsIGNsYXNzZXMgb2YgZGF0YSBpbiBSIHByb2dyYW1taW5nLiAKQ2hhcmFjdGVyIGlzIG9uZSBvZiB0aGVzZSBjbGFzc2VzLiAKQSBjaGFyYWN0ZXIgc3RyaW5nIGlzIGFuIGluZGl2aWR1YWwgZGF0YSB2YWx1ZSBtYWRlIHVwIG9mIGNoYXJhY3RlcnMuIApUaGlzIGNhbiBiZSBhIHBhcmFncmFwaCwgbGlrZSB0aGUgbGVnZW5kIGZvciB0aGUgdGFibGUsIG9yIGl0IGNhbiBiZSBhIHNpbmdsZSBsZXR0ZXIgb3IgbnVtYmVyIGxpa2UgdGhlIGxldHRlciBgImEiYCBvciB0aGUgbnVtYmVyIGAiMyJgLiAKCklmIGRhdGEgYXJlIG9mIGNsYXNzIGNoYXJhY3RlciwgdGhhbiB0aGUgbnVtZXJpYyB2YWx1ZXMgd2lsbCBub3QgYmUgcHJvY2Vzc2VkIGxpa2UgYSBudW1lcmljIHZhbHVlIGluIGEgbWF0aGVtYXRpY2FsIHNlbnNlLiAKCklmIHlvdSB3YW50IHlvdXIgbnVtZXJpYyB2YWx1ZXMgdG8gYmUgaW50ZXJwcmV0ZWQgdGhhdCB3YXksIHRoZXkgbmVlZCB0byBiZSBjb252ZXJ0ZWQgdG8gYSBudW1lcmljIGNsYXNzLiAKVGhlIG9wdGlvbnMgdHlwaWNhbGx5IHVzZWQgYXJlIGludGVnZXIgKHdoaWNoIGhhcyBubyBkZWNpbWFsIHBsYWNlKSBhbmQgZG91YmxlIHByZWNpc2lvbiAod2hpY2ggaGFzIGEgZGVjaW1hbCBwbGFjZSkuIAoKQSB2YXJpYWJsZSB0aGF0IGlzIGEgW2ZhY3Rvcl0oaHR0cHM6Ly93d3cuc3RhdC5iZXJrZWxleS5lZHUvfnMxMzMvZmFjdG9ycy5odG1sIzp+OnRleHQ9Q29uY2VwdHVhbGx5JTJDJTIwZmFjdG9ycyUyMGFyZSUyMHZhcmlhYmxlcyUyMGluLHJlZmVyZWQlMjB0byUyMGFzJTIwY2F0ZWdvcmljYWwlMjB2YXJpYWJsZXMuJnRleHQ9RmFjdG9ycyUyMGluJTIwUiUyMGFyZSUyMHN0b3JlZCx3aGVuJTIwdGhlJTIwZmFjdG9yJTIwaXMlMjBkaXNwbGF5ZWQuKSBoYXMgYSBzZXQgb2YgcGFydGljdWxhciB2YWx1ZXMgY2FsbGVkIGxldmVscy4gRXZlbiBpZiB0aGVzZSBhcmUgbnVtZXJpYywgdGhleSB3aWxsIGJlIGludGVycHJldGVkIGFzIGxldmVsIG5vdCBhcyBhIG1hdGhlbWF0aWNhbCBudW1uYmVyLiBZb3UgY2FuIG1vZGlmeSB0aGUgb3JkZXIgb2YgdGhlc2UgbGV2ZWxzIHdpdGggdGhlIGBmb3JjYXRzYCBwYWNrYWdlLgoKPC9kZXRhaWxzPgoKCioqKgoKCmBgYHtyfQpjb3VudHlfcG9wICU8PiUKICBtdXRhdGUoY291bnR5ZmlwcyA9IGFzLmZhY3Rvcihjb3VudHlmaXBzKSkKCmNvdW50eV9hcmVhICU8PiUKICBtdXRhdGUoY291bnR5ZmlwcyA9IGFzLmZhY3Rvcihjb3VudHlmaXBzKSkKYGBgCgpHcmVhdCEgTm93IHdlIGFyZSByZWFkeSB0byBjb21iaW5lIG91ciBkYXRhIHRvZ2V0aGVyLgoKV2UgY2FuIGRvIHNvIHVzaW5nIG9uZSBvZiB0aGUgIGAqX2pvaW4oKWBmdW5jdGlvbnMgb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4KClRoZXJlIGFyZSBzZXZlcmFsIHdheXMgdG8gam9pbiBkYXRhIHVzaW5nIHRoZSBgZHBseXJgIHBhY2thZ2UuCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0d2lkdGggPSAiNTAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgImpvaW4ucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2pvaW4uaHRtbCkKCkhlcmUgaXMgIGEgdmlzdWFsaXphdGlvbiBvZiB0aGVzZSBvcHRpb25zOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0d2lkdGggPSAiNTAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgImpvaW5faW1hZ2UucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3JzdHVkaW8uY29tL3Jlc291cmNlcy9jaGVhdHNoZWV0cy8pCgpTZWUgW2hlcmVdKGh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2Uvam9pbi5odG1sKSBmb3IgbW9yZSBkZXRhaWxzIGFib3V0IGpvaW5pbmcgZGF0YS4KClNpbmNlIHRoZSBwb3B1bGF0aW9uIGRhdGEgY2FtZSBmcm9tIHRoZSBBUEksIHdlIHByb2JhYmx5IGhhdmUgaW5mb3JtYXRpb24gYWJvdXQgb3Bpb2lkIHBpbGwgc2hpcG1lbnRzIGZvciBlYWNoIG9mIHRoZSBpbmNsdWRlZCBjb3VudGllcy4gU2luY2UgdGhlIGxhbmQgYXJlYSBkYXRhIGNhbWUgZnJvbSBhIGRpZmZlcmVudCBzb3VyY2UsIGl0IG1heSBjb250YWluIGFkZGl0aW9uYWwgY291bnRpZXMgdGhhdCBhcmUgbm90IGluIG91ciBwb3B1bGF0aW9uIG9yIGRydWcgc2hpcG1lbnQgZGF0YS4gIFRodXMgd2Ugd2lsbCB1c2UgdGhlIGBsZWZ0X2pvaW4oKWAgZnVuY3Rpb24gd2hlcmUgeCBpbiB0aGlzIGNhc2Ugd2lsbCBiZSB0aGUgYGNvdW50eV9wb3BgICBhbmQgeSB3aWxsIGJlIHRoZSBgY291bnRyeV9hcmVhYC4gVGh1cyB3ZSB3aWxsIGFkZCB0aGUgYExORDExMDIxMERgIChsYW5kIGFyZWEpIHZhbHVlcyBmb3IgYWxsIGNvdW50aWVzIHRoYXQgbWF0Y2ggYGNvdW50eV9wb3BgIGJhc2VkIG9uIHRoZSBgY291bnR5Zmlwc2AgY29sdW1uIHRoYXQgdGhleSBoYXZlIGluIGNvbW1vbi4gCgoKYGBge3J9CmNvdW50eV9pbmZvIDwtbGVmdF9qb2luKGNvdW50eV9wb3AsIGNvdW50eV9hcmVhKQpgYGAKCldlIGFyZSBub3cgcmVhZHkgdG8gY2FsY3VsYXRlIHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgcGVyIHNxdWFyZSBtaWxlLiBXZSBjYW4gY3JlYXRlIGEgbmV3IGNvbHVtbiB3aXRoIHRoaXMgZGF0YSB1c2luZyB0aGUgYG11dGF0ZSgpYCBmdW5jdGlvbiBhbmQgdGhlIGAvYCB0byBkaXZpZGUgdGhlIGBwb3B1bGF0aW9uYCB2YWx1ZSBieSB0aGUgbGFuZCBhcmVhIHZhbHVlIChpbiBzcXVhcmUgbWlsZXMpIGZvciBlYWNoIGNvdW50eS4gTGV0J3MgYWxzbyBtYWtlIHRoZSBgeWVhcmAgdmFyaWFibGUgYSBmYWN0b3IuCgpgYGB7cn0KY291bnR5X2luZm8gJTw+JQogIG11dGF0ZShkZW5zaXR5ID0gcG9wdWxhdGlvbi9MTkQxMTAyMTBELAogICAgICAgICB5ZWFyID0gYXMuZmFjdG9yKHllYXIpKQoKZ2xpbXBzZShjb3VudHlfaW5mbykKYGBgCgoKR3JlYXQsIG5vdyB3ZSBhcmUgcmVhZHkgdG8gY3JlYXRlIGEgdmFyaWFibGUgdGhhdCBjbGFzc2lmaWVzIGlmIGEgY291bnR5IHdhcyBydXJhbCBvciB1cmJhbiBiYXNlZCBvbiBvdXIgZGVmaW5pdGlvbiBvZiBydXJhbCBjb3VudGllcyBiZWluZyB0aG9zZSB3aXRoIGxlc3MgdGhhbiA1MDAgcGVvcGxlIHBlciBzcXVhcmUgbWlsZSBhcyB3ZWxsIGFzIHRob3NlIHdpdGggbGVzcyB0aGFuIDIsNTAwIHBlb3BsZS4gV2Ugd2lsbCB1c2UgdGhlIGBjYXNlX3doZW4oKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBjYWxzc2lmeSB0aGUgbmV3IGBydXJhbF91cmJhbmAgdmFyaWFibGUgYXMgZWl0aGVyIGAiVXJiYW4iYCBvciBgIlJ1cmFsImAgYmFzZWQgb24gdGhlIGV2YWx1YXRpb25zIG9mIHRoZSBgZGVuc2l0eWAgYW5kIHRoZSBgcG9wdWxhdGlvbmAgdmFyaWFibGVzLiBJZiB0aGUgZGVuc2l0eSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gNTAwIHBlb3BsZSBwZXIgc3F1YXJlIG1pbGUsIHRoZW4gdGhlIGNvdW50eSB3aWxsIGJlIGNvZGVkIGFzIGAiVXJiYW4iYCwgYWx0ZXJuYXRpdmVseSBpZiB0aGUgZGVuc2l0eSBpcyBsZXNzIHRoYW4gNTAwIHBlb3BsZSBwZXIgc3F1YXJlIG1pbGUgb3IgdGhlIHBvcHVsYXRpb24gaXMgbGVzcyB0aGFuIDI1MDAsIHRoYW4gdGhlIGNvdW50eSB3aWxsIGJlIGNvZGVkIGFzIGAiUnVyYWwiYC4gVGhlIGB8YCBvcHBlcmF0b3IgaXMgdXNlZCB0byBpbmRpY2F0ZSB0aGF0IGVpdGhlciBleHByZXNzaW9uIHNob3VsZCByZXN1bHQgaW4gY29kaW5nIHRoZSBjb3VudHkgYXMgYCJSdXJhbCJgCgpgYGB7cn0KCmNvdW50eV9pbmZvICU8PiUKICBtdXRhdGUocnVyYWxfdXJiYW4gPSBjYXNlX3doZW4oZGVuc2l0eSAgPj0gNTAwIH4gIlVyYmFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVuc2l0eSAgPCA1MDAgfCBwb3B1bGF0aW9uIDwgMjUwMCB+ICJSdXJhbCIpKQpgYGAKCldlIGNhbiB1c2UgdGhlIGBjb3VudCgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIHRvIHNlZSBob3cgbWFueSBvZiBlYWNoIHRoaXMgcmVzdWx0ZWQgaW46CgpgYGB7cn0KY291bnQoY291bnR5X2luZm8sIHJ1cmFsX3VyYmFuKQpgYGAKCldlIHdpbGwgbm93IGNvbWJpbmUgdGhlIGBhbm51YWxEb3NhZ2VgIGRhdGEgd2l0aCB0aGUgYGNvdW50X2luZm9gIHRpYmJsZS4KCiMjIyMgey50aGlua19xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpIb3cgbWlnaHQgd2UgZG8gdGhpcz8KCiMjIyMKCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBjb2RlLiA8L3N1bW1hcnk+CgpgYGB7cn0KYW5udWFsRG9zYWdlICU8PiUKICBtdXRhdGUoY291bnR5ZmlwcyA9IGFzLmZhY3Rvcihjb3VudHlmaXBzKSwKICAgICAgICAgICAgICAgICAgeWVhciA9IGFzLmZhY3Rvcih5ZWFyKSkKICAKQW5udWFsIDwtbGVmdF9qb2luKGFubnVhbERvc2FnZSwgY291bnR5X2luZm8pCgpgYGAKPC9kZXRhaWxzPgoKYGBge3J9CmdsaW1wc2UoQW5udWFsKQpgYGAKCkdyZWF0LCBub3cgd2Ugc2hvdWxkIGhhdmUgdGhlIGRhdGEgdGhhdCB3ZSBuZWVkIGZvciB0aGUgY2FzZSBzdHVkeS4gCgpgYGB7cixlY2hvPSBGQUxTRSwgZXZhbCA9IFRSVUV9CndyaXRlLmNzdihBbm51YWwsIGZpbGUgPSBoZXJlOjpoZXJlKCJkYXRhIiwiV3JhbmdsZWQiLCAiQW5udWFsX29waW9pZF9kYXRhLmNzdiIpKQpzYXZlKEFubnVhbCwgZmlsZSA9ICBoZXJlOjpoZXJlKCJkYXRhIiwiV3JhbmdsZWQiLCAiQW5udWFsX29waW9pZF9kYXRhLnJkYSIpKQpgYGAKCk5vdGljZSBob3cgdGhlcmUgaXMgYSB2YXJpYWJsZSBjYWxsZWQgYERPU0FHRV9VTklUYC4gVGhpcyBpbmRpY2F0ZXMgdGhlIG51bWJlciBvZiBwaWxscyBzaGlwcGVkIHRvIGEgcGhhcm1hY3kgaW4gdGhpcyBjb3VudHkgdGhhdCB3ZXJlIGVpdGhlciBbb3h5Y29kb25lXShodHRwczovL3d3dy5kZWEuZ292L3NpdGVzL2RlZmF1bHQvZmlsZXMvMjAyMC0wNi9PeHljb2RvbmUtMjAyMF8wLnBkZikgb3IgW2h5ZHJvY29kb25lXShodHRwczovL3d3dy5kZWFkaXZlcnNpb24udXNkb2ouZ292L2RydWdfY2hlbV9pbmZvL2h5ZHJvY29kb25lLnBkZikuCgpMZXQncyBkbyBhIGNoZWNrIHRvIHNlZSBob3cgY29tcGxldGUgb3VyIGRhdGEgaXMgbm93IHRoYXQgd2UgaGF2ZSBjb21iaW5lZCBvdXIgYGNvdW50cnlfaW5mb2AgZGF0YSB3aXRoIHRoZSBgbW9udGhseURvc2FnZWAgYW5kIGBhbm51YWxEb3NhZ2VgIGRhdGEuIFdlIHdpbGwgaGF2ZSBOQSB2YWx1ZXMgZm9yIGFueSBjb3VudGllcyBwcmVzZW50IGluIHRoZSBEQUUgZGF0YSBidXQgbm90IGluIG91ciBsYW5kIGFyZWEgZGF0YS4gV2UgY2FuIHVzZSB0aGUgYHZpc19taXNzKClgIGZ1bmN0aW9uIGBuYW5pYXJgIHBhY2thZ2UgdG8gY3JlYXRlIGEgcGxvdCB0aGF0IHNob3dzIGlmIHdlIGhhdmUgYW55IG1pc3NpbmcgZGF0YS4KCmBgYHtyfQpuYW5pYXI6OiBnZ19taXNzX3ZhcihBbm51YWwpCmBgYAoKIyMjIyB7LnNjcm9sbGFibGUgfQoKYGBge3J9CkFubnVhbCAlPiUKICBmaWx0ZXIoaXMubmEoU1RBVEUpKQpgYGAKIyMjIwoKVGhlcmUgZG9lcyBub3QgYXBwZWFyIHRvIGJlIGxhbmQgYXJlYSBhbmQvb3IgcG9wdWxhdGlvbiBkYXRhIGZvciB0aGVzZSBjb3VudGllcy4KYGBge3J9CmNvdW50eV9pbmZvICU+JSBmaWx0ZXIoY291bnR5ZmlwcyA9PSAiMDEwMDEiKQpjb3VudHlfaW5mbyAlPiUgZmlsdGVyKGNvdW50eWZpcHMgPT0gIjA1MDk3IikKY291bnR5X2luZm8gJT4lIGZpbHRlcihjb3VudHlmaXBzID09ICIwMjIwMSIpCmNvdW50eV9pbmZvICU+JSBmaWx0ZXIoY291bnR5ZmlwcyA9PSAiMDIyODAiKQoKIyB0aGVyZSBpcyBsYW5kIGRhdGEgZm9yIHRoaXMgY291bnR5IGJ1dCB0aGF0cyBhbGwKbGFuZCAlPiUgZmlsdGVyKFNUQ09VID09ICIwNTA5NyIpCmxhbmQgJT4lIGZpbHRlcihTVENPVSA9PSAiMDIyMDEiKQpsYW5kICU+JSBmaWx0ZXIoU1RDT1UgPT0gIjAyMjgwIikKCmNvdW50eV9wb3AgJT4lIGZpbHRlcihjb3VudHlmaXBzID09ICIwNTA5NyIpCgpjb3VudHlfcG9wICU+JSBmaWx0ZXIoY291bnR5ZmlwcyA9PSAiMDUwOTciKQpjb3VudHlfcG9wICU+JSBmaWx0ZXIoQlVZRVJfQ09VTlRZID09ICJNT05UR09NRVJZIiYgQlVZRVJfU1RBVEUgPT0iQUsiKQpgYGAKCldlIHdpbGwgbm93IHJlbW92ZSB0aGVzZSByb3dzIGJlZm9yZSBmdXJ0aGVyIGFuYWx5c2lzOgoKIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4KCkRvIHlvdSByZWNhbGwgaG93IHlvdSB3b3VsZCBkbyB0aGlzPwoKIyMjIwoKCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGNvZGUuIDwvc3VtbWFyeT4KCmBgYHtyfQoKQW5udWFsICU8PiUgZmlsdGVyKCFpcy5uYShTVEFURSkpCgpgYGAKCjwvZGV0YWlscz4KCmBgYHtyfQpuYW5pYXI6OiBnZ19taXNzX3ZhcihBbm51YWwpCmBgYAoKTmljZSEgTm93IHdlIGhhdmUgbm8gbWlzc2luZyBkYXRhLgoKIyAqKkRhdGEgQW5hbHlzaXMgYW5kIFZpc3VhbGl6YXRpb24qKgoqKioKCiMjIyBIb3cgaGFzIHBvcHVsYXRpb24gZGVuc2l0eSBjaGFuZ2VkIG92ZXIgdGhlIHllYXJzIGluIGRpZmZlcmVudCBzdGF0ZXM/CgoKYGBge3J9CmRlbnNfZGYgPC0gY291bnR5X2luZm8gICU+JSBncm91cF9ieShCVVlFUl9TVEFURSwgeWVhcikgJT4lCiAgICAgc3VtbWFyaXNlKCBtZWFuX0RFTlMgPSBtZWFuKGRlbnNpdHksIG5hLnJtID0gVFJVRSkpCgogZ2dwbG90KGRlbnNfZGYsIGFlcyh4ID1CVVlFUl9TVEFURSwgeSA9IG1lYW5fREVOUywgY29sPXllYXIsIGdyb3VwID0geWVhcikpICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGUgZGVuc2l0eSBpcyBmYWlybHkgc2ltaWxhciBmb3IgbW9zdCBzdGF0ZXMsIGhvd2V2ZXIgREMsIE1BLCBOSiwgTlksIFJJLCBhbmQgVkEgaGF2ZSBtdWNoIGhpZ2hlciBkZW5zaXRpZXMuIFdlIGFsc28gc2VlIHRoYXQgREMgc2hvd3MgdGhlIGxhcmdlc3QgY2hhbmdlIG92ZXIgdGltZS4KCgpgYGB7cn0KCiBnZ3Bsb3QoZGVuc19kZiwgYWVzKHggPXllYXIsIHkgPSBsb2cobWVhbl9ERU5TKSwgY29sPXllYXIsIGdyb3VwID0geWVhcikpICsgCiAgZ2VvbV9ib3hwbG90KCkgKyAKICBnZW9tX2ppdHRlcih3aWR0aCA9IC4xKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGxhYnMoeSA9ICJMb2cgc3RhdGUgbWVhbiBwb3B1bGF0aW9uIGRlbnNpdHkiKQoKYGBgCgoKCmBgYHtyfQoKZGVuc19kZiA8LSBjb3VudHlfaW5mbyAgJT4lIGdyb3VwX2J5KCB5ZWFyKSAlPiUKICAgICBzdW1tYXJpc2UoIG1lYW5fREVOUyA9IG1lYW4oZGVuc2l0eSwgbmEucm0gPSBUUlVFKSkKCiBnZ3Bsb3QoZGVuc19kZiwgYWVzKHggPXllYXIsIHkgPSBtZWFuX0RFTlMpKSArIAogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgoKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKHkgPSAiVVMgbWVhbiBwb3B1bGF0aW9uIGRlbnNpdHkiKQpgYGAKClRoZSBkZW5zaXR5IGRvZXNuJ3QgYXBwZWFyIHRvIGNoYW5nZSB0aGF0IG11Y2ggZnJvbSAyMDA2IHRvIDIwMTQuIAoKSG93IGRvZXMgdGhpcyBjb21wYXJlIHdpdGggcmF3IHBvcHVsYXRpb24gdmFsdWVzPwoKYGBge3J9CgpkZW5zX2RmIDwtIGNvdW50eV9pbmZvICAlPiUgZ3JvdXBfYnkoIHllYXIpICU+JQogICAgIHN1bW1hcmlzZSggdG90YWxfcG9wdWxhdGlvbiA9IHN1bShwb3B1bGF0aW9uLCBuYS5ybSA9IFRSVUUpKQoKIGdncGxvdChkZW5zX2RmLCBhZXMoeCA9eWVhciwgeSA9IHRvdGFsX3BvcHVsYXRpb24pKSArIAogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgoKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKHkgPSAiVVMgdG90YWwgcG9wdWxhdGlvbiIpCiAKYGBgCgoKIyMjIEhvdyBoYXZlIHRoZSBudW1iZXIgb2YgcnVyYWwgYW5kIHVyYmFuIGFyZWFzIGNoYW5nZWQgb3ZlciB5ZWFycz8KCmBgYHtyfQoKUl9VIDwtIGNvdW50eV9pbmZvICAlPiUgZ3JvdXBfYnkoIHllYXIpICU+JQogICAgIGNvdW50KHJ1cmFsX3VyYmFuKQoKIGdncGxvdChSX1UsIGFlcyh4ID0geWVhciwgeSA9IG4sIGNvbCA9IHJ1cmFsX3VyYmFuLCBncm91cCA9IHJ1cmFsX3VyYmFuKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBnZW9tX3Ntb290aCgpICsKICBmYWNldF93cmFwKH5ydXJhbF91cmJhbiwgc2NhbGVzID0gImZyZWUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCkl0IGxvb2tzIGFzIHRob3VnaCB0aGUgbnVtYmVyIG9mIHVyYmFuIGFyZWFzIGhhcyBpbmNyZWFzZWQsIHdoaWxlIHRoZSBudW1iZXIgb2YgcnVyYWwgYXJlYXMgaGFzIGRlY3JlYXNlZCBvdmVyIHRpbWUuCgoKYGBge3J9ClJfVSA8LSBjb3VudHlfaW5mbyAgJT4lIGdyb3VwX2J5KCB5ZWFyKSAlPiUKICAgICBjb3VudChydXJhbF91cmJhbikKUl9VICU8PiUgcGl2b3Rfd2lkZXIoIG5hbWVzX2Zyb20gPSBydXJhbF91cmJhbiwgdmFsdWVzX2Zyb20gPSBuKQpSX1UgJTw+JSB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZSgiUnVyYWwgQ2hhbmdlIiA9IFJ1cmFsIC0gbGFnKFJ1cmFsKSwgCiAgICAgICAgIlVyYmFuIENoYW5nZSI9IFVyYmFuIC0gbGFnKFVyYmFuKSwKcGVyY2VudF91cmJhbiA9IHJvdW5kKFVyYmFuLyhVcmJhbiArUnVyYWwpLDMpKjEwMCkKCmZvcm1hdHRhYmxlKFJfVSwgbGlzdChgcGVyY2VudF91cmJhbmAgPSBjb2xvcl9iYXIoIiNGQTYxNEIiKSkpCgpmb3JtYXR0YWJsZShSX1UsIGxpc3QoYHBlcmNlbnRfdXJiYW5gID0gY29sb3JfYmFyKCIjRkE2MTRCIiksCiAgICAgICAgICAgICAgICAgICAgICBgUnVyYWwgQ2hhbmdlYCA9IGZvcm1hdHRlcigic3BhbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUgPSB+c3R5bGUoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGlmZWxzZShgUnVyYWwgQ2hhbmdlYCA8IDAsICJyZWQiLCAiZ3JlZW4iKSkpLAogICAgICAgICAgICAgICAgICAgICAgYFVyYmFuIENoYW5nZWAgPSBmb3JtYXR0ZXIoInNwYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlID0gfnN0eWxlKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBpZmVsc2UoYFVyYmFuIENoYW5nZWAgPCAwLCAicmVkIiwgImdyZWVuIikpKSkpCgpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD03fQoKUl9VIDwtIGNvdW50eV9pbmZvICAlPiUgZ3JvdXBfYnkoQlVZRVJfU1RBVEUsIHllYXIpICU+JQogICAgIGNvdW50KHJ1cmFsX3VyYmFuKQpSX1UgJTw+JSBwaXZvdF93aWRlciggbmFtZXNfZnJvbSA9IHJ1cmFsX3VyYmFuLCB2YWx1ZXNfZnJvbSA9IG4pCgogIFJfVSAlPD4lbXV0YXRlKFVyYmFuID0gcmVwbGFjZV9uYShVcmJhbiAsIDApKQoKUl9VICU8PiUgbXV0YXRlKHBlcmNlbnRfdXJiYW4gPSAoVXJiYW4vKFVyYmFuK1J1cmFsKSkqMTAwKSAKIGdncGxvdChSX1UsIGNvbG9yID0gImJsYWNrIiwgYWVzKHggPSBCVVlFUl9TVEFURSwgeSA9IHBlcmNlbnRfdXJiYW4sIGNvbG9yID0geWVhcikpICsgCiAgZ2VvbV9wb2ludCgpICsgCiB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICAgY29vcmRfZmxpcCgpICsKICAgc2NhbGVfY29sb3VyX3ZpcmlkaXNfZChvcHRpb24gPSAibWFnbWEiLCBlbmQgPSAwLCBiZWdpbiA9IDEsIGd1aWRlID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSAxKSkKICAgCgpgYGAKCgoKIyMgUGlsbCBzaGlwbWVudHMgb3ZlciB0aW1lCgoKYGBge3J9CmdncGxvdChBbm51YWwgLCBhZXMoeCA9IHllYXIsIHkgPSBET1NBR0VfVU5JVCkpICsgCiAgZ2VvbV9ib3hqaXR0ZXIoKSsgCiAgbGFicyh0aXRsZSA9ICJET1NBR0VfVU5JVCBDaGFuZ2UgT3ZlciBZZWFyIikrCiAgdGhlbWVfbWluaW1hbCgpCgpgYGAKCmBgYHtyfQpBbm51YWwgICU+JSBncm91cF9ieShCVVlFUl9TVEFURSx5ZWFyKSAlPiUKICAgICBzdW1tYXJpc2UoIG1lYW5fRE9TQUdFID0gbWVhbihET1NBR0VfVU5JVCkpICU+JSB1bmdyb3VwKCkgJT4lCmdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBtZWFuX0RPU0FHRSkpICsgCiAgZ2VvbV9ib3hqaXR0ZXIoKSsgCiAgbGFicyh0aXRsZSA9ICJET1NBR0VfVU5JVCBDaGFuZ2UgT3ZlciBZZWFyIikrCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3J9CiBBbm51YWwgICU+JSBncm91cF9ieShCVVlFUl9TVEFURSx5ZWFyKSAlPiUKICAgICBzdW1tYXJpc2UoIG1lYW5fRE9TQUdFID0gbWVhbihET1NBR0VfVU5JVCkpICU+JSB1bmdyb3VwKCkgJT4lCmdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBtZWFuX0RPU0FHRSwgZ3JvdXAgPSBCVVlFUl9TVEFURSwgY29sb3IgPSBCVVlFUl9TVEFURSkpICsgCiAgZ2VvbV9saW5lKCApCmBgYAoKCmBgYHtyfQogIApnPC1Bbm51YWwgICU+JSBncm91cF9ieShCVVlFUl9TVEFURSx5ZWFyKSAlPiUKICAgICBzdW1tYXJpc2UoIG1lYW5fRE9TQUdFID0gbWVhbihET1NBR0VfVU5JVCkpICU+JSB1bmdyb3VwKCkgJT4lCmdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBtZWFuX0RPU0FHRSwgZ3JvdXAgPSBCVVlFUl9TVEFURSwgY29sb3IgPSBCVVlFUl9TVEFURSkpICsKICBnZW9tX2xpbmUoKQoKCiAgZyA8LSBnICsgZ2VvbV9wb2ludF9pbnRlcmFjdGl2ZShhZXMoCiAgICAgICAgICAgICAgICBjb2xvciA9IEJVWUVSX1NUQVRFLCAKICAgICAgICAgICAgICB0b29sdGlwID0gdXNkYXRhOjphYmJyMnN0YXRlKEJVWUVSX1NUQVRFKSksIAogICAgICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgICAgYWxwaGEgPSAzLzEwKSArdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bmUiKQogCmdpcmFmZShjb2RlID0gcHJpbnQoZykpCmBgYAoKSW4gdGhpcyBwbG90IGl0IGFwcGVhcnN0IHRoYXQgdGhlIGNvdW50aWVzIGluICBDYWxpZm9ybmlhICBnb3QgdGhlIGxhcmdlc3QgbnVtYmVyIG9mIHBpbGxzIHNoaXBwZWQuIEhvd2V2ZXIsIHNpbmNlIHdlIGRpZCBub3QgYWNjb3VudCBmb3IgcG9wdWxhdGlvbiBvciBwb3B1bGF0aW9uIGRlbnNpdHksIHRoaXMgY291bGQgc2ltcGx5IGJlIGJlY2F1c2UgaXQgaXMgdGhlIG1vc3QgcG9wdWxhdGVkIHN0YXRlLiBUbyBhY2NvdW50IGZvciB0aGlzIHdlIHdpbGwgcGVyZm9ybSBzb21ldGhpbmcgY2FsbGVkIG5vcm1hbGl6YXRpb24gdG8gbWFrZSBhIG1vcmUgZmFpciBjb21wYXJpc29uLgoKCiMjIE5vcm1hbGl6YXRpb24gb2YgcGlsbCBjb3VudAoKIyMjIE1vcm1hbGl6YXRpb24gYmFzZWQgb24gZGVuc2l0eQpgYGB7cn0KCkFubnVhbCU8PiUgIG11dGF0ZShkZW5zX0RPU0FHRSA9ICBET1NBR0VfVU5JVC8gZGVuc2l0eSkKCmdsaW1wc2UoQW5udWFsKQpgYGAKCldoeSBEZW5zaXR5IE5vcm1hbGl6YXRpb24/CgohW10ocGxvdC9ub3JtX2RlbnMucG5nKQoKCkRlc2NyaXB0aW9uIGFib3V0IGhvdyB3ZSBhbHNvIG5lZWQgbG9nIHRyYW5zZm9ybWF0aW9uCgpgYGB7ciwgZmlnLmhlaWdodCA9IDcsIGZpZy53aWR0aD04fQpwMSA8LSBnZ3Bsb3QoQW5udWFsICwgYWVzKHggPSB5ZWFyLCB5ID0gRE9TQUdFX1VOSVQsIGNvbG91ciA9IHllYXIpKSArIAogIGdlb21fYm94cGxvdCgpKyAKICBsYWJzKHRpdGxlID0gIldpdGhvdXQgTm9ybWFsaXphdGlvbiIpKwogIHRoZW1lX21pbmltYWwoKQoKCnAyIDwtIGdncGxvdChBbm51YWwsIGFlcyh4ID0geWVhciwgeSA9IGRlbnNfRE9TQUdFLCBjb2xvdXIgPSB5ZWFyKSkgKyAKICBnZW9tX2JveHBsb3QoKSsgCiAgbGFicyh0aXRsZSA9ICJEZW5zaXR5IE5vcm1hbGl6YXRpb24iKSsKICB0aGVtZV9taW5pbWFsKCkKCmdnYXJyYW5nZShwMSwgcDIsIG5yb3cgPSAyLCBuY29sPTIpCgpgYGAKCgpgYGB7cn0KCkFubnVhbCAlPiUgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gInR5cGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzX3RvICA9ICJ2YWx1ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICBjb2xzID0gYyhET1NBR0VfVU5JVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbnNfRE9TQUdFKSkgJT4lCiAgICBtdXRhdGUodHlwZSA9IGZvcmNhdHM6OmZjdF9pbm9yZGVyKHR5cGUpKSAlPiUKICBnbGltcHNlKCkKCkFubnVhbCAlPiUgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gInR5cGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzX3RvICA9ICJ2YWx1ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICBjb2xzID0gYyhET1NBR0VfVU5JVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbnNfRE9TQUdFKSkgJT4lCiAgICBtdXRhdGUodHlwZSA9IGZvcmNhdHM6OmZjdF9pbm9yZGVyKHR5cGUpKSAlPiUKCmdncGxvdCggYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGNvbG91ciA9IHllYXIpKSArIAogIGdlb21fYm94cGxvdCgpKyAKICBmYWNldF93cmFwKH50eXBlLCBzY2FsZSA9ICJmcmVlIikrCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgoKYGBgCgoKYGBge3J9CgoKQW5udWFsICU+JSBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAidHlwZSIsIAogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXNfdG8gID0gInZhbHVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHMgPSBjKERPU0FHRV9VTklULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVuc19ET1NBR0UpKSAlPiUKICBtdXRhdGUodHlwZSA9IGZvcmNhdHM6OmZjdF9pbm9yZGVyKHR5cGUpKSAlPiUKCmdncGxvdCggYWVzKHggPSB5ZWFyLCB5ID0gbG9nKHZhbHVlKSwgY29sb3VyID0geWVhcikpICsgCiAgZ2VvbV9ib3hwbG90KCkrIAogIGZhY2V0X3dyYXAofnR5cGUsIHNjYWxlID0gImZyZWUiKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCgpgYGAKCiMjIEhvdyBydXJhbCBhbmQgdXJiYW4gYXJlYXMgZGlmZmVyIGZvciBwcmVzY3JpcHRpb24gcmF0ZXMuIAoKClRoZSBnb2FsIG9mIG5vcm1hbGl6YXRpb24gaXMgdG8gbWFrZSBldmVyeSBkYXRhcG9pbnQgaGF2ZSB0aGUgc2FtZSAKc2NhbGUgc28gZWFjaCBmZWF0dXJlIGlzIGVxdWFsbHkgaW1wb3J0YW50LiAKCmBgYHtyfQpBbm51YWwgJT4lIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJ0eXBlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190byAgPSAidmFsdWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29scyA9IGMoRE9TQUdFX1VOSVQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZW5zX0RPU0FHRSApKSU+JQogIG11dGF0ZSh0eXBlID0gZm9yY2F0czo6ZmN0X2lub3JkZXIodHlwZSkpICU+JQoKZ2dwbG90KCBhZXMoeSA9IHZhbHVlLCB4ID0geWVhciwgY29sb3VyID0gcnVyYWxfdXJiYW4sIGdyb3VwID0gcnVyYWxfdXJiYW4pKSArIAogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sCiAgICAgICAgICAgICAgIGZ1bi55bWluID0gZnVuY3Rpb24oeCkgbWVhbih4KSAtIHNkKHgpLCAKICAgICAgICAgICAgICAgZnVuLnltYXggPSBmdW5jdGlvbih4KSBtZWFuKHgpICsgc2QoeCksIAogICAgICAgICAgICAgICBnZW9tID0gInBvaW50cmFuZ2UiKSArCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwKICAgICAgICAgICAgICAgZ2VvbSA9ICJsaW5lIikgKwogIGZhY2V0X3dyYXAoIH4gdHlwZSwgc2NhbGVzID0gImZyZWUiKSArCiAgbGFicyh0aXRsZSA9ICJEb3NhZ2UgQ2hhbmdlIFdpdGhvdXQgTm9ybWFsaXphdGlvbiIpKwogIHRoZW1lX21pbmltYWwoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD04fQoKcDUgPC0gZ2dwbG90KEFubnVhbCwgYWVzKHkgPSBET1NBR0VfVU5JVCwgeCA9IHllYXIsIGNvbG91ciA9IHJ1cmFsX3VyYmFuLCBncm91cCA9IHJ1cmFsX3VyYmFuKSkgKyAKICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLAogICAgICAgICAgICAgICBmdW4ueW1pbiA9IGZ1bmN0aW9uKHgpIG1lYW4oeCkgLSBzZCh4KSwgCiAgICAgICAgICAgICAgIGZ1bi55bWF4ID0gZnVuY3Rpb24oeCkgbWVhbih4KSArIHNkKHgpLCAKICAgICAgICAgICAgICAgZ2VvbSA9ICJwb2ludHJhbmdlIikgKwogIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sCiAgICAgICAgICAgICAgIGdlb20gPSAibGluZSIpICsKICBmYWNldF93cmFwKCB+IHJ1cmFsX3VyYmFuKSArCiAgbGFicyh0aXRsZSA9ICJEb3NhZ2UgQ2hhbmdlIFdpdGhvdXQgTm9ybWFsaXphdGlvbiIpKwogIHRoZW1lX21pbmltYWwoKQoKcDYgPC0gZ2dwbG90KEFubnVhbCAsIGFlcyh5ID0gZGVuc19ET1NBR0UsIHggPSB5ZWFyLCBjb2xvdXIgPSBydXJhbF91cmJhbiwgZ3JvdXAgPSBydXJhbF91cmJhbikpICsgCiAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwKICAgICAgICAgICAgICAgZnVuLnltaW4gPSBmdW5jdGlvbih4KSBtZWFuKHgpIC0gc2QoeCksIAogICAgICAgICAgICAgICBmdW4ueW1heCA9IGZ1bmN0aW9uKHgpIG1lYW4oeCkgKyBzZCh4KSwgCiAgICAgICAgICAgICAgIGdlb20gPSAicG9pbnRyYW5nZSIpICsKICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLAogICAgICAgICAgICAgICBnZW9tID0gImxpbmUiKSArCiAgZmFjZXRfd3JhcCggfiAgcnVyYWxfdXJiYW4pICsKICBsYWJzKHRpdGxlID0gIkRvc2FnZSBDaGFuZ2UgLSBEZW5zaXR5IE5vcm1hbGl6YXRpb24iKSsKICB0aGVtZV9taW5pbWFsKCkKCgoKZ2dhcnJhbmdlKHA1LCBwNiwgbmNvbD0gMiApCgpgYGAKCgojIyB0LXRlc3QKCmh0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvd2lraS91bnBhaXJlZC10d28tc2FtcGxlcy10LXRlc3QtaW4tcgoKYGBge3J9CnQudGVzdChET1NBR0VfVU5JVCB+IHJ1cmFsX3VyYmFuLCBkYXRhID0gQW5udWFsLCB2YXIuZXF1YWwgPSBUUlVFKQoKdC50ZXN0KGRlbnNfRE9TQUdFIH4gcnVyYWxfdXJiYW4sIGRhdGEgPSBBbm51YWwsIHZhci5lcXVhbCA9IFRSVUUpCgpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGUgcmVzdWx0IGlzIGRpZmZlcmVudCBkZXBlbmRpbmcgb24gaG93IHdlIG5vcm1hbGl6ZSB0aGUgZGF0YSEKCiMgKipTdW1tYXJ5KioKKioqIAoKIyMgU3VtbWFyeSBQbG90CgojIyBTeW5vcHNpcwoKSW4gdGhpcyBjYXNlIHN0dWR5IHdlIGhhdmUgZGVtb25zdHJhdGVkIHRoZSBiYXNpY3Mgb2YgUiBNYXJrZG93biBhbmQgaG93IHRvIGNyZWF0ZSBhIGRhc2hib2FyZCB3aXRoIHVzaW5nIHRoZSBgZmxleGRhc2hib2FyZGAgcGFja2FnZS4gV2UgYWxzbyBkZW1vbnN0cmF0ZWQgaG93IHRvIGluY2x1ZGUgYW4gaW50ZXJhY3RpdmUgdGFibGUgd2l0aCB0aGUgYERUYCBwYWNrYWdlLCBob3cgdG8gaW5jbHVkZSBpbnRlcmFjdGl2ZSBwbG90cyB1c2luZyBmdW5jdGlvbnMgb2YgdGhlIGBzaGlueWAgcGFja2FnZSBzdWNoIGFzIGByZW5kZXJQbG90KClgLiBXZSBhbHNvIGluY2x1ZGVkIGludGVyYWN0aXZlIHZhbHVlIGJveGVzIHVzaW5nIHRoZSBgcmVuZGVyVmFsdWVCb3goKWAgZnVuY3Rpb24gb2YgdGhlIGBmbGV4ZGFzaGJvYXJkYCBwYWNrYWdlIHdoaWNoIHdvcmtzIHdpdGggdGhlIGBzaGlueWAgcGFja2FnZS4gRmluYWxseSB3ZSBhbHNvIHNob3dlZCBob3cgdG8gaW5jbHVkZSBpbnRlcmFjdGl2ZSBtYXBzIHVzaW5nIHRoZSBgbGVhZmxldGAgcGFja2FnZS4gCgpUaGlzIGNhc2Ugc3R1ZHkgYWxzbyBleHBsb3JlZCBob3cgdG8gcHJvcGVybHkgY2FsY3VsYXRlIGFuZCBpbnRlcnByZXQgcGVyY2VudGFnZXMgd2hlbiB0aGUgZGF0YSBoYXMgbWlzc2luZyB2YWx1ZXMuIFdlIGFsc28gZGlzY3Vzc2VkIHRoZSBiZW5lZml0cyBhbmQgbGltaXRpbmcgYXNwZWN0cyBvZiBwaWUgY2hhcnRzICh1c2luZyBgZ2dwbG90MmApIGFuZCB3YWZmbGUgcGxvdHMgKHVzaW5nIGB3YWZmbGVgKS4KCk92ZXJhbGwgdGhlIGRhc2hib2FyZCB0aGF0IHdlIGNyZWF0ZWQgc2hvd3MgdGhhdCB0aGUgbnVtYmVyIG9mIHNob290aW5ncyBwZXIgeWVhciBoYXMgaW5jcmVhc2VkIG92ZXJ0aW1lLiBGdXJ0aGVyIGludmVzdGlnYXRpb24gaXMgbmVjZXNzYXJ5IHRvIGRldGVybWluZSBpZiB0aGlzIGlzIHNpbXBseSBkdWUgdG8gaW5jcmVhc2VzIGluIHBvcHVsYXRpb24gYWxvbmUgb3IgaWYgdGhlIHJhdGUgaGFzIGluY3JlYXNlZCBkdWUgdG8gb3RoZXIgZmFjdG9ycyBhbmQgaWYgc28sIHdoYXQgdGhvc2UgZmFjdG9ycyBtaWdodCBiZS4gSXQgaXMgYWxzbyBjbGVhciB0aGF0IHRoZSBudW1iZXIgb2Ygc2hvb3RpbmdzIGFuZCB0aGUgbnVtYmVyIG9mIGRlYXRocyBwZXIgY2FwaXRhIHZhcmllcyBieSBzdGF0ZS4gVGh1cyB0aGVyZSBhcHBlYXJzIHRvIGJlIG90aGVyIGFzcGVjdHMgYWNjb3VudGluZyBmb3Igc3RhdGUgZGlmZmVyZW5jZXMuIAoKIyAqKlN1Z2dlc3RlZCBIb21ld29yayoqCioqKiAKCkNyZWF0ZSBhbm90aGVyIGRhc2hib2FyZCB3aXRoIGdyYXBocyBhbmQgc3RhdGlzdGljcyBmZWF0dXJpbmcgb3RoZXIgZWxlbWVudHMgd2l0aGluIHRoaXMgZGF0YXNldC4gRm9yIGV4YW1wbGUsIHN0dWRlbnRzIG1heSBjcmVhdGUgZ3JhcGhzIHRoYXQgZXhwbG9yZSB3aGF0IHNjaG9vbCBldmVudHMgYXJlIHJlcG9ydGVkIHRvIGhhdmUgbW9yZSBzaG9vdGluZ3MuCgoKIyAqKkFkZGl0aW9uYWwgSW5mb3JtYXRpb24qKgoqKioKCiMjIEhlbHBmdWwgTGlua3MKCltSU3R1ZGlvXShodHRwczovL3JzdHVkaW8uY29tL3Byb2R1Y3RzL3JzdHVkaW8vZmVhdHVyZXMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0NoZWF0c2hlZXQgb24gUlN0dWlkbyBJREVdKGh0dHBzOi8vZ2l0aHViLmNvbS9yc3R1ZGlvL2NoZWF0c2hlZXRzL3Jhdy9tYXN0ZXIvcnN0dWRpby1pZGUucGRmKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW090aGVyIFJTdHVkaW8gY2hlYXRzaGVldHNdKGh0dHBzOi8vcnN0dWRpby5jb20vcmVzb3VyY2VzL2NoZWF0c2hlZXRzLyl7dGFyZ2V0PSJfYmxhbmsifSAgIApbUlN0dWRpbyBwcm9qZWN0c10oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei93b3JrZmxvdy1wcm9qZWN0cy5odG1sKQoKW1RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAKCiAgIAoKW1BpcGluZyBpbiBSXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbWFncml0dHIvdmlnbmV0dGVzL21hZ3JpdHRyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAKCltTdHJpbmcgbWFuaXB1bGF0aW9uIGNoZWF0c2hlZXRdKGh0dHBzOi8vcnN0dWRpby5jb20vcmVzb3VyY2VzL2NoZWF0c2hlZXRzLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltUYWJsZSBmb3JtYXRzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9XaWRlX2FuZF9uYXJyb3dfZGF0YSl7dGFyZ2V0PSJfYmxhbmsifQoKW0dlb2NvZGluZ10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR2VvY29kaW5nKSAgCltDb29yZGluYXRlIHJlZmVyZW5jZSBzeXN0ZW0gKENSUyldKGh0dHBzOi8vd3d3LnczLm9yZy8yMDE1L3NwYXRpYWwvd2lraS9Db29yZGluYXRlX1JlZmVyZW5jZV9TeXN0ZW1zKSBbRVNQR10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRVBTR19HZW9kZXRpY19QYXJhbWV0ZXJfRGF0YXNldCkKW1dvcmxkIEdlb2RldGljIFN5c3RlbSAoV0dTKSB2ZXJzaW9uIDg0IGFsc28gY2FsbGVkIEVTUEc6NDMyNiBdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dvcmxkX0dlb2RldGljX1N5c3RlbSNXR1M4NCkgICAKW0FsYmVycyBlcXVhbC1hcmVhIGNvbmljIHByb2plY3Rpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FsYmVyc19wcm9qZWN0aW9uIzp+OnRleHQ9VGhlJTIwQWxiZXJzJTIwZXF1YWwlMkRhcmVhJTIwY29uaWMsdGhhdCUyMHVzZXMlMjB0d28lMjBzdGFuZGFyZCUyMHBhcmFsbGVscy4mdGV4dD1UaGUlMjBBbGJlcnMlMjBwcm9qZWN0aW9uJTIwaXMlMjB1c2VkLHRoZSUyMFVuaXRlZCUyMFN0YXRlcyUyMENlbnN1cyUyMEJ1cmVhdS4pICAgCltjcnMgMTAyMDA4XShodHRwczovL3NwYXRpYWxyZWZlcmVuY2Uub3JnL3JlZi9lc3JpLzEwMjAwOC9odG1sLykgIAoKVG8gbGVhcm4gbW9yZSBhYm91dCBnZW9zcGF0aWFsIGNvb3JkaW5hdGUgc3lzdGVtcyBzZWUgW2hlcmVdKGh0dHBzOi8vd3d3Lm5jZWFzLnVjc2IuZWR1L3NpdGVzL2RlZmF1bHQvZmlsZXMvMjAyMC0wNC9PdmVydmlld0Nvb3JkaW5hdGVSZWZlcmVuY2VTeXN0ZW1zLnBkZikgYW5kIFtoZXJlXShodHRwczovL2d1aWRlcy5saWJyYXJ5LmR1a2UuZWR1L3ItZ2Vvc3BhdGlhbC9DUlMpLgoKCltgZ2dwbG90MmAgcGFja2FnZV0oaHR0cDovL2dncGxvdDIudGlkeXZlcnNlLm9yZyl7dGFyZ2V0PSJfYmxhbmsifSAgICAKUGxlYXNlIHNlZSBbdGhpcyBjYXNlIHN0dWR5XShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vb2NzLWJwLWNvMi1lbWlzc2lvbnMvKSAgZm9yIG1vcmUgZGV0YWlscyBvbiB1c2luZyBgZ2dwbG90MmAgICAgCltncmFtbWFyIG9mIGdyYXBoaWNzXShodHRwOi8vdml0YS5oYWQuY28ubnovcGFwZXJzL2xheWVyZWQtZ3JhbW1hci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgCltgZ2dwbG90MmAgdGhlbWVzXShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2d0aGVtZS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgCgpbTW90aXZhdGluZyBhcnRpY2xlIGZvciB0aGlzIGNhc2Ugc3R1ZHkgYWJvdXQgc2Nob29sIHNob290aW5nc10oaHR0cHM6Ly9saW5rLnNwcmluZ2VyLmNvbS9jb250ZW50L3BkZi8xMC4xMDA3L3MxMTkyMC0wMTItMDMzMS02LnBkZikKCkFsc28gc2VlIHRoaXMgW2FydGljbGVdKGh0dHBzOi8vc2llcHIuc3RhbmZvcmQuZWR1L3NpdGVzL2RlZmF1bHQvZmlsZXMvcHVibGljYXRpb25zLzE5LTAzNi5wZGYpIHRvIGxlYXJuIG1vcmUgYWJvdXQgdGhlIGltcGFjdHMgb2Ygc2Nob29sIHNob290aW5ncy4KCgpbTGlnaHR3ZWlnaHQgbWFya3VwIGxhbmd1YWdlcyhMTUwpXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaWdodHdlaWdodF9tYXJrdXBfbGFuZ3VhZ2UpICAKW01hcmtkb3duXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NYXJrZG93bikgIApbUiBtYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS8pICAgCltga25pdHJgXShodHRwczovL3lpaHVpLm9yZy9rbml0ci8pICAKW2BybWFya2Rvd25gIChwYWNrYWdlKV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JtYXJrZG93bi9ybWFya2Rvd24ucGRmKQoKU2VlIHRoaXMgW2Jvb2tdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi8pIGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHdvcmtpbmcgd2l0aCBSIE1hcmtkb3duIGZpbGVzLiAKClRoZSBSU3R1ZGlvIFtjaGVhdHNoZWV0IGZvciBSIE1hcmtkb3duXShodHRwczovL2dpdGh1Yi5jb20vcnN0dWRpby9jaGVhdHNoZWV0cy9yYXcvbWFzdGVyL3JtYXJrZG93bi0yLjAucGRmKSBhbmQgdGhpcyBbdHV0b3JpYWxdKGh0dHBzOi8vb3VyY29kaW5nY2x1Yi5naXRodWIuaW8vdHV0b3JpYWxzL3JtYXJrZG93bi8pIGFyZSBncmVhdCBmb3IgZ2V0dGluZyBzdGFydGVkLiAKCltQYW5kb2NdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BhbmRvYykgIAoKW1lBTUxdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1lBTUwpICAKW0NvbmZpZ3VyYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbmZpZ3VyYXRpb25fZmlsZSkgIAoKW2ZsZXhkYXNoYm9hcmRdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2ZsZXhkYXNoYm9hcmQvKSAgCgpTZWUgW2hlcmVdKGh0dHBzOi8vcnN0dWRpby5jb20vcmVzb3VyY2VzL3dlYmluYXJzL2ludHJvZHVjaW5nLWZsZXhkYXNoYm9hcmRzLykgZm9yIGEgdmlkZW8gYWJvdXQgZmxleGRhc2hib2FyZCBhbmQgW2hlcmVdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2ZsZXhkYXNoYm9hcmQvKSBmb3IgYSBtb3JlIGluZm9ybWF0aW9uIG9uIGhvdyB0byB1c2UgdGhpcyBwYWNrYWdlLiAgIApTZWUgW2hlcmVdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2ZsZXhkYXNoYm9hcmQvdXNpbmcuaHRtbCNjb21wb25lbnRzKSBmb3IgYSBsaXN0IG9mIG90aGVyIHBhY2thZ2VzIHRoYXQgYXJlIHVzZWZ1bCBmb3IgYWRkaW5nIGVsZW1lbnRzIHRvIGRhc2hib2FyZHMgY3JlYXRlZCB3aXRoIHRoZSBgZmxleGRhc2hib2FyZGAgcGFja2FnZS4gICAKU2VlIFtoZXJlXShodHRwczovL3d3dy5kYXRhZHJlYW1pbmcub3JnL3Bvc3Qvci1tYXJrZG93bi10aGVtZS1nYWxsZXJ5LykgZm9yIGEgbGlzdCBvZiBSIE1hcmtkb3duIHRoZW1lcyB3aGljaCBjYW4gYmUgdXNlZCB3aXRoIGBmbGV4ZGFzaGJhcmRgLiAgIApTZWUgW0ZvbnQgQXdlc29tZV0oaHR0cHM6Ly9mb250YXdlc29tZS5jb20vaWNvbnM/ZD1nYWxsZXJ5KSBmb3IgaWNvbnMuICAKClRvIGxlYXJuIG1vcmUgYWJvdXQgdXNpbmcgYHNoaW55YCB3aXRoIHRoZSBgZmxleGRhc2hib2FyZGAgcGFja2FnZSB0byBjcmVhdGUgaW50ZXJhY3RpdmUgZGFzaGJvYXJkcywgc2VlIHRoaXMgW3R1dG9yaWFsXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9mbGV4ZGFzaGJvYXJkL3NoaW55Lmh0bWwpLiAgIAoKW2xlYWZsZXQgKFIgcGFja2FnZSldKGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vbGVhZmxldC8pICAgCltMZWFmbGV0IChKYXZhU2NyaXB0IExpYnJhcnkpXShodHRwczovL2xlYWZsZXRqcy5jb20vKSAgIAoKW3NoaW55XShodHRwczovL3NoaW55LnJzdHVkaW8uY29tLykgIApTZWUgW2hlcmVdKGh0dHBzOi8vc2hpbnkucnN0dWRpby5jb20vZ2FsbGVyeS8pIGZvciBhIGdhbGxlcnkgb2YgYHNoaW55YCBleGFtcGxlcy4KClNlZSB0aGlzIFt3ZWJzaXRlXShodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL3NoaW55ZGFzaGJvYXJkLykgdG8gbGVhcm4gYWJvdXQgYSBtb3JlIGZsZXhpYmxlIGFuZCBzbGlnaHRseSBtb3JlIGNoYWxsZW5naW5nIG9wdGlvbiBmb3IgY3JlYXRpbmcgZGFzaGJvYXJkcyBpbiBSIHVzaW5nIGEgcGFja2FnZSBjYWxsZWQgYHNoaW55ZGFzaGJvYXJkYC4KCgo8dT4qKlBhY2thZ2VzIHVzZWQgaW4gdGhpcyBjYXNlIHN0dWR5OioqIDwvdT4KClBhY2thZ2UgICB8IFVzZSBpbiB0aGlzIGNhc2Ugc3R1ZHkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEgIApbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pIHwgIHRvIGltcG9ydCB0aGUgZGF0YSAgYXMgYSBjc3YgZmlsZSAgCltnb29nbGVzaGVldHM0XShodHRwczovL2dvb2dsZXNoZWV0czQudGlkeXZlcnNlLm9yZy8pIHwgdG8gaW1wb3J0IGRpcmVjdGx5IGZyb20gR29vZ2xlIFNoZWV0cwpbdGliYmxlXShodHRwczovL3RpYmJsZS50aWR5dmVyc2Uub3JnLykgfCB0byBjcmVhdGUgdGliYmxlcyAodGhlIHRpZHl2ZXJzZSB2ZXJzaW9uIG9mIGRhdGFmcmFtZXMpCltkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZmlsdGVyLCBzdWJzZXQsIGpvaW4sIGFkZCByb3dzIHRvLCBhbmQgbW9kaWZ5IHRoZSBkYXRhICAKW3N0cmluZ3JdKGh0dHBzOi8vc3RyaW5nci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gbWFuaXB1bGF0ZSAgY2hhcmFjdGVyIHN0cmluZ3Mgd2l0aGluIHRoZSBkYXRhIChjb2xsYXBzaW5nIHN0cmluZ3MgdG9nZXRoZXIsIHJlcGxhY2UgdmFsdWVzLCBhbmQgZGV0ZWN0IHZhbHVlcykKW21hZ3JpdHRyXShodHRwczovL21hZ3JpdHRyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBwaXBlIHNlcXVlbnRpYWwgY29tbWFuZHMgClt0aWR5cl0oaHR0cHM6Ly90aWR5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gY2hhbmdlIHRoZSBzaGFwZSBvciBmb3JtYXQgb2YgdGliYmxlcyB0byB3aWRlIGFuZCBsb25nLCB0byBkcm9wIHJvd3Mgd2l0aCBgTkFgIHZhbHVlcywgYW5kIHRvIHNlZSB0aGUgbGFzdCBmZXcgY29sdW1ucyBvZiBhIHRpYmJsZQpbZ2dtYXBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZ21hcC9nZ21hcC5wZGYpIHwgdG8gZ2VvY29kZSB0aGUgZGF0YSAod2hpY2ggbWVhbnMgZ2V0IHRoZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIHZhbHVlcykKW3NmXShodHRwczovL3Itc3BhdGlhbC5naXRodWIuaW8vc2YvKSB8IHRvIG1vZGlmeSB0aGUgZ2VvY29kZWQgZGF0YSBzbyB0aGF0IG92ZXJsYXBwaW5nIHBvaW50cyBkaWQgbm90IG92ZXJsYXAKW2x1YnJpZGF0ZV0oaHR0cHM6Ly9sdWJyaWRhdGUudGlkeXZlcnNlLm9yZy8pIHwgdG8gd29yayB3aXRoIHRoZSBkYXRhLXRpbWUgZGF0YSAgICAKW0RUXShodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL0RULykgfCB0byBjcmVhdGUgdGhlIGludGVyYWN0aXZlIHRhYmxlICAKW2h0bWx0b29sc10oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL2h0bWx0b29scy92ZXJzaW9ucy8wLjUuMCkgfCB0byBhZGQgYSBjYXB0aW9uIHRvIG91ciBpbnRlcmFjdGl2ZSB0YWJsZSAKW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gY3JlYXRlIHBsb3RzICAKW2dnZm9yY2VdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZ2ZvcmNlL2dnZm9yY2UucGRmKSAgIHwgdG8gY3JlYXRlIGEgcGxvdCB6b29tCltmb3JjYXRzXShodHRwczovL2ZvcmNhdHMudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHJlb3JkZXIgZmFjdG9yIGZvciBwbG90Clt3YWZmbGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9ocmJybXN0ci93YWZmbGUpIHwgdG8gbWFrZSB3YWZmbGUgcHJvcG9ydGlvbiBwbG90cyAgCltwb2xpc2NpZGF0YV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BvbGlzY2lkYXRhL3BvbGlzY2lkYXRhLnBkZikgfCB0byBnZXQgcG9wdWxhdGlvbiB2YWx1ZXMgZm9yIHRoZSBzdGF0ZXMKW2ZsZXhkYXNoYm9hcmRdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2ZsZXhkYXNoYm9hcmQvKSAgICAgfCB0byBjcmVhdGUgdGhlIGRhc2hib2FyZCAgCltzaGlueV0oaHR0cHM6Ly9zaGlueS5yc3R1ZGlvLmNvbS8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGFsbG93IG91ciBkYXNoYm9hcmQgdG8gYmUgaW50ZXJhY3RpdmUgICAKW2xlYWZsZXRdKGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vbGVhZmxldC9zaGlueS5odG1sKSB8IHRvIGltcGxlbWVudCB0aGUgW2xlYWZsZXRdKGh0dHA6Ly9sZWFmbGV0anMuY29tLykgKGEgSmF2YVNjcmlwdCBsaWJyYXJ5IGZvciBtYXBzKSB0byBjcmVhdGUgdGhlIG1hcCBmb3Igb3VyIGRhc2hib2FyZCAgIAoKCiMjIyMgey5lbXBoYXNpc19ibG9ja30KCgpJZiB5b3Ugb3IgYSBsb3ZlZCBvbmUgaXMgc3R1Z2dsaW5nIHdpdGggb3Bpb2lkIGFkZGljdGlvbiwgY29udGFjdCB0aGUgU0FNSFNB4oCZcyBOYXRpb25hbCBIZWxwbGluZSBhdCBbMS04MDAtNjYyLUhFTFAgKDQzNTcpXSh0ZWw6MS04MDAtNjYyLUhFTFAgKDQzNTcpKS4gCgpJdCBpcyBhIGZyZWUsIGNvbmZpZGVudGlhbCwgMjQvNywgMzY1LWRheS1hLXllYXIgdHJlYXRtZW50IHJlZmVycmFsIGFuZCBpbmZvcm1hdGlvbiBzZXJ2aWNlIChpbiBFbmdsaXNoIGFuZCBTcGFuaXNoKSBmb3IgaW5kaXZpZHVhbHMgYW5kIGZhbWlsaWVzIGZhY2luZyBtZW50YWwgYW5kL29yIHN1YnN0YW5jZSB1c2UgZGlzb3JkZXJzLgoKWW91IGNhbiBhbHNvIGNvbnRhY3QgdGhlIFtBZGRpY3Rpb24gQ2VudGVyXShodHRwczovL3d3dy5hZGRpY3Rpb25jZW50ZXIuY29tL2RydWdzL292ZXJkb3NlLykgYXQgWyg4NzcpODcxLTM1NzVdKHRlbDo4Nzc4NzEtMzU3NSkgd2hpY2ggYWxzbyBoYXMgYSBjb25maWRlbnRpYWwgMjQvNyBsaXZlIGNoYXQgYXQ6CltodHRwczovL3d3dy5hZGRpY3Rpb25jZW50ZXIuY29tL2RydWdzL292ZXJkb3NlL10oaHR0cHM6Ly93d3cuYWRkaWN0aW9uY2VudGVyLmNvbS9kcnVncy9vdmVyZG9zZS8pLgoKQWNjb3JkaW5nIHRvIHRoZWlyIHdlYnNpdGU6Cgo+UmVtZW1iZXIsIHRoYXQgYmVpbmcgYWJsZSB0byB0cmVhdCBhbiBvdmVyZG9zZSBhdCBob21lIGlzIG5vdCBhIHJlcGxhY2VtZW50IGZvciBhIGhvc3BpdGFsLiBFdmVuIGlmIHRoZSBtb21lbnQgaGFzIHBhc3NlZCwgYW5kIHRoZSB2aWN0aW0gc2VlbXMgZmluZSwgdGhlcmUgaXMgc3RpbGwgYSBjaGFuY2UgdGhhdCBzb21ldGhpbmcgaXMgZ29pbmcgb24gdGhhdCBjYW5ub3QgYmUgc2VlbiBieSB0aGUgaHVtYW4gZXllLiBUYWtpbmcgdGhlIHZpY3RpbSB0byB0aGUgaG9zcGl0YWwsIGNhbiBtZWFuIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gbGlmZSBhbmQgZGVhdGguCgo+IE92ZXJkb3NlIGlzIGEgc2Nhcnkgd29yZC4gV2Ugb2Z0ZW4gYXNzb2NpYXRlIGl0IHdpdGggZGVhdGgsIGJ1dCB0aGUgdHdvIGFyZSBub3QgYWx3YXlzIGNvbm5lY3RlZC4gTGlmZSBjYW4gZ28gb24gYWZ0ZXIgYW4gb3ZlcmRvc2UsIGJ1dCBvbmx5IGlmIHRoZSBwZXJzb24gc3VmZmVyaW5nIHVuZGVyc3RhbmRzIGFuZCBsZWFybnMgZnJvbSBpdC4gR2V0dGluZyBvbiB0aGUgcm9hZCB0byByZWNvdmVyeSBpcyBub3QgZWFzaWx5IGRvbmUgYnV0IGl0IGlzIGFsd2F5cyBwb3NzaWJsZSwgYW5kIHRoZSBvbmx5IGd1YXJhbnRlZWQgd2F5IHRvIG5ldmVyIHN1ZmZlciBhbiBvdmVyZG9zZSBhZ2Fpbi4gSWYgeW91IGRvbuKAmXQga25vdyB3aGVyZSB0aGlzIHBhdGggYmVnaW5zLCBvciBuZWVkIGhlbHAgZ2V0dGluZyBoZWxwIGZvciBhIGxvdmVkIG9uZSwgcGxlYXNlIHJlYWNoIG91dCB0byBhIGRlZGljYXRlZCB0cmVhdG1lbnQgcHJvdmlkZXIuIFRoZXnigJlyZSBoZXJlLCAyNC83LCB0byBhbnN3ZXIgYW55IHF1ZXN0aW9ucyB5b3UgbWF5IGhhdmUuIEJlIGl0IGZvciB5b3Vyc2VsZiBvciBzb21lb25lIGVsc2UuCgpBY2NvcmRpbmcgdG8gW2hhcm1yZWR1Y3Rpb24ub3JnXShodHRwczovL2hhcm1yZWR1Y3Rpb24ub3JnL2lzc3Vlcy9vdmVyZG9zZS1wcmV2ZW50aW9uL292ZXJ2aWV3L292ZXJkb3NlLWJhc2ljcy9yZWNvZ25pemluZy1vcGlvaWQtb3ZlcmRvc2UvKSwgdGhlIGZvbGxvd2luZyBhcmUgc2lnbnMgb2YgYW4gb3ZlcmRvc2U6CgotIExvc3Mgb2YgY29uc2Npb3VzbmVzcwotVW5yZXNwb25zaXZlIHRvIG91dHNpZGUgc3RpbXVsdXMKLSBBd2FrZSwgYnV0IHVuYWJsZSB0byB0YWxrCi0gQnJlYXRoaW5nIGlzIHZlcnkgc2xvdyBhbmQgc2hhbGxvdywgZXJyYXRpYywgb3IgaGFzIHN0b3BwZWQKLSBGb3IgbGlnaHRlciBza2lubmVkIHBlb3BsZSwgdGhlIHNraW4gdG9uZSB0dXJucyBibHVpc2ggcHVycGxlLCBmb3IgZGFya2VyIHNraW5uZWQgcGVvcGxlLCBpdCB0dXJucyBncmF5aXNoIG9yIGFzaGVuLgotIENob2tpbmcgc291bmRzLCBvciBhIHNub3JlLWxpa2UgZ3VyZ2xpbmcgbm9pc2UgKHNvbWV0aW1lcyBjYWxsZWQgdGhlIOKAnGRlYXRoIHJhdHRsZeKAnSkKLSBWb21pdGluZwotIEJvZHkgaXMgdmVyeSBsaW1wCi0gRmFjZSBpcyB2ZXJ5IHBhbGUgb3IgY2xhbW15Ci0gRmluZ2VybmFpbHMgYW5kIGxpcHMgdHVybiBibHVlIG9yIHB1cnBsaXNoIGJsYWNrCi0gUHVsc2UgKGhlYXJ0YmVhdCkgaXMgc2xvdywgZXJyYXRpYywgb3Igbm90IHRoZXJlIGF0IGFsbAogCklmIHNvbWVvbmUgaXMgbWFraW5nIHVuZmFtaWxpYXIgc291bmRzIHdoaWxlIOKAnHNsZWVwaW5n4oCdIGl0IGlzIHdvcnRoIHRyeWluZyB0byB3YWtlIGhpbSBvciBoZXIgdXAuIE1hbnkgbG92ZWQgb25lcyBvZiB1c2VycyB0aGluayBhIHBlcnNvbiB3YXMgc25vcmluZywgd2hlbiBpbiBmYWN0IHRoZSBwZXJzb24gd2FzIG92ZXJkb3NpbmcuIFRoZXNlIHNpdHVhdGlvbnMgYXJlIGEgbWlzc2VkIG9wcG9ydHVuaXR5IHRvIGludGVydmVuZSBhbmQgc2F2ZSBhIGxpZmUuCgpTb21ldGltZXMgaXQgY2FuIGJlIGRpZmZpY3VsdCB0byB0ZWxsIGlmIGEgcGVyc29uIGlzIGp1c3QgdmVyeSBoaWdoLCBvciBleHBlcmllbmNpbmcgYW4gb3ZlcmRvc2UuICBJZiB5b3XigJlyZSBoYXZpbmcgYSBoYXJkIHRpbWUgdGVsbGluZyB0aGUgZGlmZmVyZW5jZSwgaXQgaXMgYmVzdCB0byB0cmVhdCB0aGUgc2l0dWF0aW9uIGxpa2UgYW4gb3ZlcmRvc2Ug4oCTIGl0IGNvdWxkIHNhdmUgc29tZW9uZeKAmXMgbGlmZS4KCioqVGhlIG1vc3QgaW1wb3J0YW50IHRoaW5nIGlzIHRvIGFjdCByaWdodCBhd2F5ISoqCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9taXJvLm1lZGl1bS5jb20vbWF4LzcwMC8xKkNkaVNBcjNPb21WRkhDNl8xRV9YS3cucG5nIikKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vbWVkaXVtLmNvbS9kci1taW5nLWthby9vcGlvaWQtYWR2ZXJzZS1lZmZlY3RzLWFsdGVybmF0aXZlcy0zZmFlNjZiN2QyNDcpCgojIyMjCgojIyBTZXNzaW9uIEluZm8KCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAoKCiMjIEFja25vd2xlZGdlbWVudHMKCldlIHdvdWxkIGxpa2UgdG8gYWNrbm93bGVkZ2UgW0VsaXphYmV0aCBTdHVhcnRdKGh0dHBzOi8vd3d3Lmpoc3BoLmVkdS9mYWN1bHR5L2RpcmVjdG9yeS9wcm9maWxlLzE3OTIvZWxpemFiZXRoLWEtc3R1YXJ0KSBmb3IgYXNzaXN0aW5nIGluIGZyYW1pbmcgdGhlIG1ham9yIGRpcmVjdGlvbiBvZiB0aGUgY2FzZSBzdHVkeS4KCldlIHdvdWxkIGFsc28gbGlrZSB0byBhY2tub3dsZWRnZSB0aGUgW0Jsb29tYmVyZyBBbWVyaWNhbiBIZWFsdGggSW5pdGlhdGl2ZV0oaHR0cHM6Ly9hbWVyaWNhbmhlYWx0aC5qaHUuZWR1LykgZm9yIGZ1bmRpbmcgdGhpcyB3b3JrLiAKCg==